> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Dependencies

## Overview

With Dependencies, you can replace parts of Spree core with your custom code:
[Services and Workflows](/docs/v5/developer/customization/workflows), CanCanCan
Abilities (used for [Permissions](/docs/v5/developer/customization/permissions)), and API Serializers (used for
generating JSON API responses).

<Tip>
  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](/docs/v5/developer/customization/workflows#extending-a-workflow-with-hooks)
  instead. Hooks survive upgrades.
</Tip>

## 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:

```ruby theme={"theme":"night-owl"}
Spree.cart_update_service = MyStore::CartUpdate
```

or using the block syntax:

```ruby theme={"theme":"night-owl"}
Spree.dependencies do |dependencies|
  dependencies.cart_update_service = MyStore::CartUpdate
end
```

Now let's create your custom service.

```bash theme={"theme":"night-owl"}
mkdir -p app/services/my_store && touch app/services/my_store/cart_update.rb
```

And add the following code to it:

```ruby theme={"theme":"night-owl"}
module MyStore
  class CartUpdate < Spree::Carts::Update
    def call(cart:, params:)
      result = super

      MyStore::ErpSync.push(result.value) if result.success?

      result
    end
  end
end
```

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`:

```ruby theme={"theme":"night-owl"}
module MyStore
  class AddItem < Spree::Carts::AddItem
    def perform(variant:, cart: nil, **rest)
      super

      # your logic, then the standard result
    end
  end
end

Spree.cart_add_item_workflow = MyStore::AddItem
```

<Note>
  Before writing this, check whether a
  [hook](/docs/v5/developer/customization/workflows#available-hooks) 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.
</Note>

## Using dependencies in your code

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

```ruby theme={"theme":"night-owl"}
# Returns the resolved class (not a string)
Spree.cart_add_item_workflow.call(cart: cart, variant: variant, quantity: 1)

# For API dependencies, use the Spree.api accessor
Spree.api.storefront_cart_serializer.new(order).serializable_hash
```

## Controller level customization

If you need to replace [serializers](https://github.com/jsonapi-serializer/jsonapi-serializer) or Services in a specific API endpoint you can create a [code decorator](/docs/v5/developer/customization/decorators):

```bash theme={"theme":"night-owl"}
mkdir -p app/controllers/spree && touch app/controllers/spree/cart_controller_decorator.rb
```

and add the following code to it:

```ruby theme={"theme":"night-owl"}
module Spree
  module CartControllerDecorator
    def resource_serializer
      MyNewAwesomeCartSerializer
    end

    def add_item_service
      MyNewAwesomeAddItemToCart
    end
  end

  CartController.prepend(CartControllerDecorator)
end
```

This will change the serializer in this API endpoint to `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](https://github.com/spree/spree/tree/main/api/app/controllers/spree/api/v3) 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:

```ruby theme={"theme":"night-owl"}
Spree.api.storefront_cart_serializer = MyNewAwesomeCartSerializer
Spree.api.storefront_cart_add_item_service = MyNewAwesomeAddItemToCart
```

This will swap the default Cart serializer and Add Item to Cart service for your custom ones within all Storefront API endpoints that use those classes.

You can mix and match both global and API-level customizations:

```ruby theme={"theme":"night-owl"}
Spree.cart_add_item_workflow = MyNewAwesomeAddItemToCart
Spree.api.storefront_cart_add_item_service = AnotherAddItemToCart
```

The second line will have precedence over the first one, and the Storefront API will use `AnotherAddItemToCart` and the rest of the application will use `MyNewAwesomeAddItemToCart`.

## Debugging dependencies

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

### List all dependencies

```bash theme={"theme":"night-owl"}
bin/rake spree:dependencies:list
```

This will output all dependencies with their current values:

```
[CORE]
cart_add_item_workflow          Spree::Carts::AddItem
carts_create_service            Spree::Carts::Create
cart_recalculate_workflow       Spree::Carts::Recalculate [OVERRIDDEN]
...

[API]
storefront_cart_serializer      Spree::V2::Storefront::CartSerializer
storefront_cart_add_item_service  MyApp::CartAddItem [OVERRIDDEN]
...
```

You can use `grep` to filter results:

```bash theme={"theme":"night-owl"}
bin/rake spree:dependencies:list | grep cart
```

### Show only overridden dependencies

```bash theme={"theme":"night-owl"}
bin/rake spree:dependencies:overrides
```

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

```
[Core OVERRIDES]
cart_recalculate_workflow  Spree::Carts::Recalculate -> MyApp::CartRecalculate (config/initializers/spree.rb:15)

[API OVERRIDES]
storefront_cart_add_item_service  Spree::Carts::AddItem -> MyApp::CartAddItem (config/initializers/spree.rb:20)
```

### Validate all dependencies

```bash theme={"theme":"night-owl"}
bin/rake spree:dependencies:validate
```

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:

```
..........F.........
1 invalid dependencies:
  [Core] cart_add_item_workflow: uninitialized constant NonExistentClass
```

## Programmatic introspection

You can also inspect dependencies programmatically:

```ruby theme={"theme":"night-owl"}
# Check all current values
Spree::Dependencies.current_values
# => [{name: :cart_add_item_workflow, current: MyApp::CartAddItem, default: 'Spree::Carts::AddItem', overridden: true}, ...]

# Check if a specific dependency is overridden
Spree::Dependencies.overridden?(:cart_add_item_workflow)
# => true

# Get override information (where it was set)
Spree::Dependencies.override_info(:cart_add_item_workflow)
# => {value: MyApp::CartAddItem, source: "config/initializers/spree.rb:15", set_at: 2024-01-15 10:30:00}

# Validate all dependencies resolve to valid classes
Spree::Dependencies.validate!
# => true (or raises Spree::DependencyError)
```

## Renamed seams in Spree 6.0

Seams backed by a [workflow](/docs/v5/developer/customization/workflows) were renamed
from `*_service` to `*_workflow` in 6.0:

| Legacy name                       | Current name                       |
| --------------------------------- | ---------------------------------- |
| `cart_add_item_service`           | `cart_add_item_workflow`           |
| `cart_recalculate_service`        | `cart_recalculate_workflow`        |
| `carts_complete_service`          | `carts_complete_workflow`          |
| `cart_merge_strategy`             | `cart_merge_workflow`              |
| `order_cancel_service`            | `order_cancel_workflow`            |
| `order_complete_service`          | `order_complete_workflow`          |
| `fulfillment_create_service`      | `fulfillment_create_workflow`      |
| `payments_handle_webhook_service` | `payments_handle_webhook_workflow` |

<Warning>
  The legacy names stay readable for one release, 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. The legacy names are removed in Spree 6.1.
</Warning>

## Backwards compatibility

The legacy string-based syntax is still supported for backwards compatibility:

```ruby theme={"theme":"night-owl"}
# Legacy syntax (still works)
Spree::Dependencies.carts_create_service = 'MyStore::CartCreate'
result = Spree::Dependencies.carts_create_service.constantize

# New syntax (recommended)
Spree.carts_create_service = MyStore::CartCreate
result = Spree.carts_create_service
```

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:
   * [Application (global) dependencies](https://github.com/spree/spree/blob/main/core/lib/spree/core/dependencies.rb)
   * [API level dependencies](https://github.com/spree/spree/blob/main/api/lib/spree/api/dependencies.rb)
