Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Latest commit

 

History

History
127 lines (92 loc) · 3.88 KB

logic.md

File metadata and controls

127 lines (92 loc) · 3.88 KB
title section order
Business Logic
customization
4

Business Logic

Overview

It is highly recommended to use Dependencies and Extensions first rather than to apply patches to Spree Core. Still if you don't find those to be efficient you can pretty much overwrite any part of Spree following this guide.

Extending Classes

All of Spree's business logic (models, controllers, helpers, etc) can easily be extended or overridden to meet your exact requirements using standard Ruby idioms.

Standard practice for including such changes in your application or extension is to create a file within the relevant app/models/spree or app/controllers/spree directory with the original class name with _decorator appended.

Extending Models

Adding a custom method to the Product model: app/models/my_store/spree/product_decorator.rb

module MyStore
  module Spree
    module ProductDecorator
      def self.prepended(base)
        base.before_validation :strip_whitespaces
      end

      def some_method
        ...
      end

      protected

      def strip_whitespaces
        ...
      end
    end
  end
end

::Spree::Product.prepend MyStore::Spree::ProductDecorator if ::Spree::Product.included_modules.exclude?(MyStore::Spree::ProductDecorator)

Adding new associations to existing models

Assume you want to add a new model called Video associated to Spree::Product. Let's start with creating a database migration:

bundle exec rails g migration CreateVideos url:string product:references
bundle exec rails db:migrate

Add new model to app/models/videos.rb:

class Video < ApplicationRecord
  belongs_to :product, class_name: 'Spree::Product'
end

Finally add the association in ProductDecorator in app/models/my_store/spree/product_decorator.rb:

module MyStore
  module Spree
    module ProductDecorator
      def self.prepended(base)
        base.has_many :videos, class_name: 'Video', foreign_key: 'product_id', dependent: :destroy
      end
    end
  end
end

::Spree::Product.prepend MyStore::Spree::ProductDecorator if ::Spree::Product.included_modules.exclude?(MyStore::Spree::ProductDecorator)

Extending Controllers

Adding a custom action to the ProductsController: app/controllers/my_store/spree/products_controller_decorator.rb

module MyStore
  module Spree
    module ProductsControllerDecorator
      def some_action
        ...
      end
    end
  end
end

::Spree::ProductsController.prepend MyStore::Spree::ProductsControllerDecorator if ::Spree::ProductsController.included_modules.exclude?(MyStore::Spree::ProductsControllerDecorator)

The exact same format can be used to redefine an existing method.

Accessing Product Data

If you extend the Products controller with a new method, you may very well want to access product data in that method. You can do so by using the :load_data before_action.

module MyStore
  module Spree
    module ProductsControllerDecorator
      def self.prepended(base)
        base.before_action :load_data, only: :some_action
      end

      def some_action
        ...
      end
    end
  end
end

::Spree::ProductsController.prepend MyStore::Spree::ProductsControllerDecorator if ::Spree::ProductsController.included_modules.exclude?(MyStore::Spree::ProductsControllerDecorator)

:load_data will use params[:id] to lookup the product by its permalink.

Replacing Models or Controllers

If your customizations are so large that you overwrite the majority of a given Model or Controller we recommend to drop the _decorator pattern and overwrite the Model or Controller completely in your project. This will make future Spree upgrades easier.