Skip to main content

Overview

With Dependencies, you can replace parts of Spree core with your custom code: Services and Workflows, the staff ability class and the storefront access policy (used for Permissions), and API Serializers (used for generating JSON API responses).
Replacing a whole class means keeping your copy in sync with every Spree release. If you only need to run code inside an existing flow — validating, reacting, or contributing data to a calculation — use a hook instead. Hooks survive upgrades.

Application (global) customization

This will change every aspect of the application (the Store API, the Admin API, and everything built on them). In your config/initializers/spree.rb file, you can set the following:
or using the block syntax:
Now let’s create your custom service.
And add the following code to it:
Inheriting and calling super keeps Spree’s behaviour and adds yours around it, which is usually what you want — a full rewrite means re-implementing logic that changes between releases.

Replacing a workflow

Workflow-backed seams end in _workflow (cart_add_item_workflow, carts_complete_workflow, payment_capture_workflow, …). A replacement subclasses the workflow and overrides perform:
Before writing this, check whether a hook covers your case — carts.add_item.validate and carts.add_item.after_item_added handle most reasons people replace this class, and they don’t need maintaining across upgrades.
A subclass runs its hooks under its own key, derived from its class name — MyStore::AddItem fires my_store.add_item.*, not carts.add_item.*. Hooks registered on the original key (by you or by an installed extension) stop firing once you swap the class in. To keep them, declare the original key in the subclass:

Using dependencies in your code

When you need to use a dependency in your code, you can access it directly via the Spree module:

Controller level customization

If you need to replace a serializer in a specific API endpoint only, you can create a code decorator:
and add the following code to it:
This will change the serializer in this API endpoint to MyNewAwesomeCartSerializer. Services and workflows are resolved through the global dependencies (e.g. Spree.cart_add_item_workflow), so swap those at the application level. Different API endpoints can have different dependency injection points. You can review their source code to see what you can replace.

API level customization

API serializers have their own injection points under Spree.api — Store API serializers (cart_serializer, product_serializer, …) and Admin API serializers (admin_order_serializer, …) — so you can customize one surface without touching the other. In your Spree initializer (config/initializers/spree.rb) please add:
This will swap the default serializers for your custom ones within all API endpoints that use them.

Debugging dependencies

Spree provides rake tasks to help you debug and inspect dependencies:

List all dependencies

This will output all dependencies with their current values:
You can use grep to filter results:

Show only overridden dependencies

This shows only the dependencies that have been customized, along with their original and current values:

Validate all dependencies

This validates that all dependencies can be resolved to valid classes. If any dependency points to a non-existent class, it will report an error:

Programmatic introspection

You can also inspect dependencies programmatically:

Seams backed by a workflow

Seams backed by a workflow use a *_workflow name, not *_service:
The legacy names stay readable, but assigning to one no longer has any effect — the override is recorded and a deprecation warning names the seam to port to. A class written against the old service contract isn’t interchangeable with the workflow the new call sites use, so applying it silently would break checkout in ways that are hard to trace.If you override any of these, move to the *_workflow name and make sure your class subclasses the workflow.
Two seams are plain renames with an unchanged contract, so an override set under the old name is still applied (with a deprecation warning): checkout_add_store_credit_service → store_credit_apply_service and checkout_remove_store_credit_service → store_credit_remove_service. All legacy names are removed in Spree 6.1.

Backwards compatibility

The legacy string-based syntax is still supported for backwards compatibility:
Both syntaxes can coexist, but the new syntax is recommended as it’s more concise and provides better error messages at assignment time.

Default values

Default values can be easily checked by:
  1. Using the rake task: bin/rake spree:dependencies:list
  2. Looking at the source code: