Overview
With Dependencies, you can easily replace parts of Spree core with your custom code. You can replace Services, CanCanCan Abilities (user for Permissions), and API Serializers (used for generating JSON API responses).
Application (global) customization
This will change every aspect of the application (both APIs, Admin Panel, and Storefront).
In your config/initializers/spree.rb file, you can set the following:
Spree::Dependencies.cart_add_item_service = 'MyAddToCartService'
Spree.dependencies do |dependencies|
  dependencies.cart_add_item_service = 'MyAddToCartService'
end
mkdir app/services -f && touch app/services/my_add_to_cart_service.rb
module MyAddToCartService < Spree::Cart::AddItem
  def call(order:, variant:, quantity: nil, public_metadata: {}, private_metadata: {}, options: {})
    ApplicationRecord.transaction do
      run :add_to_line_item
      run Spree::Dependencies.cart_recalculate_service.constantize
      run :update_in_external_system
    end
  end
  private
  def update_in_external_system(new_order_line_item)
    # Your custom logic here
  end
end
- Inherit from Spree::Cart::AddItem
- Override the callmethod to add your custom logic
- Call run :add_to_line_itemto add the item to the cart
- Call run Spree::Dependencies.cart_recalculate_service.constantizeto recalculate the cart
- Call run :update_in_external_systemto execute your custom logic, eg. updating Order in an external system such as ERP
Values set in the initializer have to be strings, eg. 'MyNewAwesomeAddItemToCart'
Controller level customization
If you need to replace serializers or Services in a specific API endpoint you can create a code decorator:
mkdir app/controllers/spree -f && touch app/controllers/spree/cart_controller_decorator.rb
module Spree
  module CartControllerDecorator
    def resource_serializer
      MyNewAwesomeCartSerializer
    end
    def add_item_service
      MyNewAwesomeAddItemToCart
    end
  end
  CartController.prepend(CartControllerDecorator)
end
MyNewAwesomeCartSerializer and also it will swap the default add_item_service to MyNewAwesomeAddItemToCart.
Different API endpoints can have different dependency injection points. You can review their source code to see what you can replace.
API level customization
Storefront API and Platform API have separate Dependencies injection points so you can easily customize one without touching the other.
In your Spree initializer (config/initializers/spree.rb) please add:
Spree::Api::Dependencies.storefront_cart_serializer = 'MyNewAwesomeCartSerializer'
Spree::Api::Dependencies.storefront_cart_add_item_service = 'MyNewAwesomeAddItemToCart'
Spree::Dependencies.cart_add_item_service = 'MyNewAwesomeAddItemToCart'
Spree::Api::Dependencies.storefront_cart_add_item_service = 'AnotherAddItemToCart'
AnotherAddItemToCart and the rest of the application will use MyNewAwesomeAddItemToCart
Default values
By default values can be easily checked by looking at the source code of Dependencies classes: