For what a cart reports and how to read it, see
Carts. This page is about
adding to it.
Requirements are the gate, steps are a label
Two things are easy to confuse:- A requirement is enforced. It appears on cart reads while unmet, and completing a cart recomputes the list and refuses if anything is outstanding.
- A step is descriptive. It exists so a storefront can render a progress indicator. Nothing on the server checks which step a customer is on.
Adding a requirement
When the flow is unchanged and you only need one more condition:server/config/initializers/spree.rb
satisfied: returns false the cart reports the requirement and refuses to
complete. Its code is derived as <field>_required — vat_number_required here.
The storefront satisfies it by writing the value into the cart’s metadata. When the
cart is completed, its metadata is copied onto the order — onto every order if the
checkout is split between sellers — so the VAT number is still there after placement as
order.metadata['vat_number'].
Pass applicable: to scope it. It is checked before satisfied:, so a requirement
that doesn’t apply never appears at all:
message is stored verbatim — wrap it in Spree.t yourself if it needs translating.
Adding a step
A step bundles its own requirements and says when it is satisfied:server/config/initializers/spree.rb
current_step and completed_steps, its
requirements appear in requirements while unsatisfied, and completion refuses the
cart until they are met.
Each lambda receives the cart. Placement is controlled by two keywords:
An unanchored step lands immediately before
complete. An anchor naming a step this
particular cart doesn’t have — before: :payment on a free cart — falls back to the
same place.
Unlike an added requirement, a step’s requirements: lambda may set its own code:.
Reordering or removing built-in steps
server/config/initializers/spree.rb
Prefer a requirement to a workflow hook
A workflow hook oncarts.complete.validate
can also reject a cart, and there are cases for it — anything needing a network call, or a
decision that only makes sense at the moment of completion.
For anything a customer has to fix, a requirement is better: it is reported on every
cart read, so the storefront can show it while they can still act, rather than failing
at the last step with an error they have to interpret.
Related
- Carts — reading requirements and completing a cart
- Custom fields — storing your own data on a cart
- Services & Workflows — hooks that run during completion

