Spree Commerce

Try It Now

Upcoming Changes to Checkout Customization

Posted on July 11, 2012 by radar

A lot of our users have complained about how hard it is to customize the checkout flow of Spree. Some of our users wanted to remove the delivery step when
shoppers had only digital goods in their cart. Others wanted to remove all the steps except for address. Another group wanted to be able to add steps to the
checkout process in between the currently existing steps.

Currently, you need to override the entire state machine inside the Spree::Order class to do this, even including events that you shouldn’t need to care
about, such as cancel and return authorizations.

We’ve recently had a long discussion about this on an issue brought up by one of our users, Colin Gemmell. In this
instance, Colin wanted to re-define the state machine, but ran into problems where in doing so, it would raise spammy warnings about method redefinitions.
It would seem that the current practice of overriding the entire state machine is a bad idea.

So to fix this, we thought about the problem for quite a while. What we’ve come up with after quite a lot of thinking about it is a tidy DSL that will allow you to define the checkout flow for orders in a Spree store. This DSL is built on top of the DSL that the state_machine gem provides, and looks like this:

Order.class_eval do
  checkout_flow do
    go_to_state :address
    go_to_state :delivery
    go_to_state :payment, :if => lambda { payment_required? }
    go_to_state :confirm, :if => lambda { confirmation_required? }
    go_to_state :complete
    remove_transition :from => :delivery, :to => :confirm

This new DSL is all about not redefining the entire state machine. Everyone who’s attempted to customize the checkout process has inevitably done so because they wanted to alter the checkout flow. That’s what this new DSL will allow you to do. Rather than editing the entire state machine, the new DSL will only define the transitions that are to happen during the next event, which is what is used during the checkout process.

This new checkout_flow is used to define the flow of the checkout around each Order object. The go_to_state method will define a transition from the previous state into the new state. If the go_to_state call has an if on the end of it, it will keep track of all states until it finds a state that does not have a conditional. Once that happens, transitions will be defined for the intermediary states.

The remove_transition method will remove the transition specified, if it exists.

To understand this better, take a look at this handy image:

Given the above state machine, the following transitions will be defined:

  • Cart to Address
  • Address to Delivery
  • Delivery to Payment
  • Delivery to Confirm
  • Delivery to Complete
  • Payment to Confirm
  • Payment to Complete
  • Confirm to Complete

The “Delivery to Confirm” transition will be removed by the remove_transition call however, meaning that it will be impossible for orders to transition from delivery to confirm.

We believe this will make it easier for people to customize the state machine than has ever been possible before. Look for it in the next Spree release!