Major/new features


Removing support for Ruby 1.8.7

Support for Ruby 1.8.7 is going away in this major release. If you are still using 1.8.7, it is time to upgrade. Ruby 1.8.7 is End of Life’d at the end of June

Upgrading to Ruby 1.9.3 or higher is highly encouraged. Spree 2.0 and above supports Ruby 2.

Splitting up core

A lot of people have requested the ability to use either the backend or the frontend separately from the other. We did a lot of work toward this goal as part of #2225 and now Spree is split up into the following components:

  • API
  • Backend
  • Core
  • Dash
  • Frontend
  • Sample

The Backend component provides the admin interface for Spree and the Frontend component provides the frontend user-facaing checkout interface. These components were extracted out of Core to allow for users of Spree to override the frontend or backend functionality of Spree as they choose. Core now contains just the very basic needs for Spree.

Along with this work, the Promo engine has now been merged with Spree core. We saw that there was a lot of hackery going on to get promos to work with Core, and a lot of stores want promos anyway, and so merging them made sense.

Additionally, as part of this work, the spree_core assets have been renamed. In store/all.css and store/all.js, you will need to rename the references from spree_core to spree_frontend. Similarly to this, in admin/all.css and admin/all.js, you will need to rename the references from spree_core to spree_backend.

Split shipments

Complex Spree stores require sophisticated shipping and warehouse logic that Spree hasn’t had a general solution for until now. Split shipments in Spree allows for multiple shipments per order and for those shipments to be shipped from multiple locations.

There are 4 main components that make up split shipments: Stock Locations, Stock Items, Stock Movements and Stock Transfers.

Stock locations

Stock locations are the locations where your inventory is shipped from. Each stock location can have many stock items. When creating a new stock location, stock items for that location are automatically created for each variant in your store.

Having multiple stock locations allows for more robust shipping options. For example, if an item in an order is out of stock at the location of the other items in a order, a new shipment may be created if that item is found to be in stock at another location.

You are also able to create and manage orders that have items from multiple locations by using the improved admin interface.

Stock items

Stock Items represent the inventory at a stock location for a specific variant. Stock item count on hand can be increased or decreased by creating stock movements. Because these are created automatically for each location you create, there is no need to manually manage these.

Stock movements

Stock movements allow you to manage the inventory of a stock item for a stock location. Stock movements are created in the admin interface by first navigating to the product you want to manage. Then, follow the Stock Management link in the sidebar.

For more information on split shipments and how they pertain to inventory management, read the Inventory Guide.

For more information on the classes introduced by split shipments and how to work with them programmatically, see the Shipments Guide.

Stock transfers

Stock transfers allow you to move inventory in bulk from one stock location to another stock location.

Stock transfers generally consist of a source location, a destination location, one or more variants and an optional reference number. Stock transfers can also be used as a way to track new stock, in which case only a stock location destination and variant are required.


Spree 2.0 now comes with namespaced translations so that translations in your application will no longer conflict with those within Spree. It’s recommended that if you have extension that uses Spree to move its translations into the Spree namespace to avoid the same problem.

Translations within Spree views should now use the Spree.t helper, rather than the t helper so that they are namespaced correctly.


New API endpoints

API clients can now manage the following resources through the API:

  • Option Types
  • Option Values
  • Inventory Units
  • Shipments
  • Stock Items
  • Stock Locations
  • Stock Movements

The documentation for these endpoints hasn’t been written yet, but will be shortly.

Instance level permissions

The API now can enforce instance-level permissions on objects. This means that some users would be able to access a single item within a resource, rather than an “all or none” approach to the API.

commit 548dc0c5

Custom API templates

If you wish to use a custom template for an API response you can do this by passing in a template parameter to API requests.

Read the documentation for more information.


Adjustment state changes

Adjustments can now be open, closed or finalized, allowing for a more flexible adjustments system. An ‘open’ adjustment can be modified, whereas a ‘closed’ adjustment cannot. Finalized adjustments are never altered.

commit 43a3cca4


Order population responsibility has been moved out to its own class. This has been done so that the API, Core and any other extensions that wish to use the order population logic have an easy way to do so.

See #2341 and commit 432d129c for more information.


Coupon application responsibility has been moved out to its own class too. This has been done so that the API, Core and any other extensions that wish to apply coupons have an easy way to do so.

commit 8ac9ac1c


Product duplication code has been moved out to its own class as well.


New helpers to modify checkout flow steps

To add or remove steps to the checkout flow, you can now use the insert_checkout_step and remove_checkout_step helpers respectively. This patch has been backported to 1-3-stable as well, and will be available in Spree releases >= 1.3.3.

The insert_checkout_step takes a before or after option to determine where to insert the step:

insert_checkout_step :new_step, :before => :address
# or
insert_checkout_step :new_step, :after => :address

The remove_checkout_step will remove just one checkout step at a time:

remove_checkout_step :address
remove_checkout_step :delivery


Minor changes



The Spree API now has support for “checking out” an order. This API functionality allows an existing order to be updated and advanced until it is in the complete state.

For instance, if you have an order in the “confirm” state that you would like to advance to the “complete” state, make the following request:

PUT /api/checkouts/ORDER_NUMBER

For more information on using the new CheckoutsController, please see the Checkouts API Documentation.

Versioned templates

API responses can now be versioned by the versioncake gem. While this is not used in Spree at the moment, it is future-proofing the API.


Auto-rotation of images

Images will now be auto-rotated to their correct orientation based on EXIF data from the original image. All EXIF data is then stripped from the image, resulting in a smaller final image size.


Sample data

The sample data now exists within straight Ruby code. The previous YAML-backed configuration was confusing and led to invalid data being inserted for sample data.

commit cc2f55a2

Unique payment identifier

Some payment gateways require payments to have a unique identifier. To solve this problem in Spree, each payment now has an identifier attribute which is generated when the payment is created.

#1998 commit b543fd10

Removal of CheckoutController#state_callback

The state_callback method in CheckoutController has been removed. Instead of this method, please use transition callbacks on the Order.state_machine instance instead.

Tracking URL for shipments

Shipping methods now have the ability to have tracking URLs. These can be used to track the shipments on external shipping providers’ websites.


Mailers now can take IDs or model objects

To help with potential background processing of mailers, all mailer actions can now take the ID of their respective object, or the object itself.


SSLRequirement deprecated in favour of ForceSSL

Spree will now use the config.force_ssl setting of Rails to determine whether or not to use SSL.


MailMethod model no longer exists

The MailMethod model no longer exists. Instead, it is a class and all configuration is now done through that class or through Spree::Config settings.


Trivial changes

Some of these changes may have made it into 1-3-stable or 1-2-stable as well. You may wish to check that branch for commits with the same message to make sure of this.

  • ShippingMethod labels can now be overriden by overriding the adjustment_label method. #2222
  • Promotion rules that respond to #products will have their products considered in promotion adjustments. #2363
  • Taxons and products are now joined with a Classification model. #2532 commit 0c594923
  • Fix call to select_month and select_year #2259
  • Fix issue where params[:keyword], not params[:keywords] was acknowledged on taxons/show.html.erb. #2258 #2270
  • Allow overriding of a shipping address’s label #2222
  • Guard against false positive Jirafe conversions #2273 #2211 #2157
  • Add first_name and last_name aliases for Addresses commit ad119f9e
  • Escape JavaScript within ecommerce tracking code #2289
  • Slight refactoring of how preferences are fetched from preference store commit bddc49a5
  • Fix issue where “New State” button on country page would not link to correct country. #2281
  • Order#checkout_steps will now always include complete commit 5110e121
  • Fix issue where flash[:commerce_tracking] was hanging around too long. #2287
  • Remove colons from translations in mail templates #2278
  • A payment method can now control its auto_capture? method. #2304
  • Added a preference to display a product without a price. #2302
  • Improve ‘out of stock’ error message. #1821
  • Track IP addresses for orders, for payment gateway reasons. #2216 #2257
  • Use protocol-specific URL for font. #2316
  • First order promotion will now work with guest users. #2306
  • Always show resend button on admin order page. #2318
  • Allow a shipment to be made ‘ready’ once order has been made ‘resumed’ #2317
  • PerItem calculator no longer fails if a rule doesn’t respond to the products method. #2322
  • attachment_url can now be configured from the admin backend. #2344
  • Scale and precision have been corrected in split_prices_from_variants migration. #2358
  • Localize error message for email validator. #2364 #2729 #2730
  • Remove duplicate thumbnails on products/show. #2361
  • Use line item price, not variant price, in return authorization price calculation JS. #2342
  • Allow for a product’s description to be put to the page raw #2323 #2874 commit 30fdf083. See also commit b616d84a and #2518.
  • Promotions can now apply to orders which were created before the promotion. #2388 #2395
  • Allow Address#phone validation to be overridden. #2394
  • Sort properties by alphabetical order on prototype form. #2389
  • Introduce datepicker_field_value for displaying datepicker field values. #2405
  • The ‘New Product’ button now appears on the edit product page. #2407
  • option values in Variant#options_text are now sorted in a predictable order. #2432
  • link_to_cart can now be used outside of Spree contexts. #2441
  • Promotion adjustments will now be removed on orders which are not complete when the promotion is deleted. #1046 #2453
  • Adjustments are now displayed on the orders/show template. #2449
  • Variant images are displayed in place of product images in admin/images #2228
  • Product properties are now sortable. #2464
  • Returned items can now be re-shipped. #2475
  • LogEntry records are now saved for failed payments #1767
  • Show full address in order confirmation #2136 #2511
  • Retrieve a list of variants from an order by calling Order#variants. #2195
  • Fix group_by_products_id sometimes not being available as a scope. #1247
  • Allow meta_description on Spree::Product to be as long as text will allow, rather than string. #2611
  • Fix currency display issues when using Euro. #2634
  • Fix issue where orders would become “locked” when initial payment had failed. #2616 #2570 #2678 #2585 #2652
  • Check for unprocessed payments before transitioning to complete state #2694
  • Added check to prevent skipping of checkout steps. #2280
  • Improve the look of the coupon code on the checkout. #2720
  • Admin tabs are now only displayed if user is authorized to see them. #2626
  • Reduce minimum characters required for variant autocomplete #2774
  • Added helper methods to shipment to calculate shipment item and total costs #2843
  • Allow product scopes to be added to from an extension #2608
  • Fix routing error caused by routing-filter and previous ghetto implementation of taxon autocomplete. #2248
  • ActionMailer settings will no longer be re-configured if they’re already set. #2855
  • Fix issue where tax calculator computed taxes incorrectly for non-VAT taxes. #2870
  • The coupon code field is now hidden when there are no possible coupon codes. #2835
  • The position attribute for variants is now computed once the variant is saved. #2744
  • Account for situation where current_order might return nil in an OrdersController#update call. #2750
  • Fix case where ActiveMerchant would incorrectly process currencies without 2 decimal places. #2930
  • Add US military states to default states. #2769
  • Allow for specially overridden attributes for line items in the API. #2916
  • Transition order as far to complete as it will go after editing customer details. #2950 #2433
  • Fix issue where going back a step in a cart could cause a undefined method run_callbacks error to be raised. #2959 #2921
  • Use DISTINCT ON to make product in_taxon scope really distinct in PostgreSQL #2851
  • Run order update hooks when order is finalized too #2986