WARNING: Some of the information here has been made redundant by later changes.
Work has been done to reduce the likelihood of new projects needing to override the default Spree layout template . The title, stylesheets, and logo now can all be customized without creating your own copy of the layout.
There are some new methods for manipulating the page title: the and helper methods in Spree::BaseController.
Use to set a page title either from a controller method, or a view template. You can also override the and methods in Spree::BaseController for further control.
The method is used in of the new release, however if you are upgrading and want to take advantage, use this in between your tags of your layout template:
<%= title %>
And to set the title in a view template:
<% set_title ‘My custom title’ %>
is a new config option for customizing the stylesheets used by the default application layout. The value of is a comma-separated string of stylesheet names without the file extensions. See the customization guide for more information.
If you are upgrading, to take advantage of this use the new helper method.
is a new config option for customizing the logo image path.
If you are upgrading, take advantage of this by using the new helper method.
There has been significant refactoring to the implementation of calculators. Calculators are now polymorphic and belong to . This will have a non trivial impact on your existing store configuration. After upgrading to Spree 0.9.0 you are likely going to have to make several manual adjustments to the existing tax and shipping configurations. Ultimately we feel this is outweighed by the superior design of the new calculator system which will allow for a more modular design.
WARNING: Many of the existing calculator extensions are not yet updated to support Spree 0.9.0. Please check the extension registry to see which versions are supported. Our goal is to back port most of the useful calculators out there shortly after the release.
All calculators need to implement the following methoddef compute(something=nil) … end
The calculator is passed an optional “target” on which to base their calculation. This method is expected to return a single numeric value when the calculation is complete. A value of should be returned in the event that a charge is not applicable.
Since calculators are now instances of they can be configured with preferences. Each instance of is now stored in the database along with the configured values for its preferences. This allows the same calculator (ex. ) to be used with multiple , and yet each can be configured with different values (ex. different amounts per calculator.)
Calculators are configured using Spree’s flexible preference system. Default values for the preferences are configured through the class definition. For example, the flat rate calculator class definition specifies an amount with a default value of 0.class Calculator::FlatRate < Calculator preference :amount, :decimal, :default => 0 … end
Spree now contains a standard mechanism by which calculator preferences can be edited. The screenshot below shows how the amounts for the flat rate calculator are now editable directly in the admin interface.
Calculators are now stored in a special directory located within . There are several calculators included that meet many of the standard store owner needs. Developers are encouraged to write their own extensions to supply additional functionality or to consider using a third party extension written by members of the Spree community.
Calculators need to be “registered” with Spree in order to be made available in the admin interface for various configuration options. The recommended approach for doing this is via an extension. Custom calculators will typically be written as extensions so you need to add some registration logic to the extension containing the calculator. This will allow the calculator to do a one time registration during the standard extension activation process.
The that is included in the Spree core is a good example of how you can achieve this in your own custom extensions.def activate [ Calculator::FlatPercent, Calculator::FlatRate, Calculator::FlexiRate, Calculator::PerItem, Calculator::SalesTax, Calculator::Vat, ].each(&:register) end
This calls the method on the calculators that we intend to register. Spree provides a mechanism for extension authors to specify the operations for which the calculator is intended. For example, a flat rate calculator might be useful for all operations but another calculator may be appropriate only for coupons and not shipping or taxes.
Models that are declared with maintains their own set of registered calculators. Currently this includes , , and . The following example shows how to configure a calculator to make it available for use with .
INFO: Spree automatically configures your calculators for you when using the basic install and/or third party extensions. This discussion is intended to help developers and others interested in understanding the desgin behind calculators.
Once your calculators have been registered correctly by your extensions, then they will become available as options in the appropriate admin screens.
There are also minor changes to how taxes are configured. You no longer need to specify sales tax or VAT but you do need to choose a calculator type. Tax rates are configured as preferences for the calculator itself.
WARNING: Your tax rates will be lost when you run the migrations. You will have to recreate them manually in the admin interface.
Spree 0.9.0 provides a new flexible system of adjustments associated with orders. The table no longer has separate columns for , , etc. This information is now captured more generically as an . This allows a Spree application to add more then one tax or shipping charge per order as well as to support new types of charges that might be required. For instance, some products for sale (like cell phones) require a separate activation fee.
Adjustments come in two basic flavors: and . From an implementation perspective, they are both modeled in a single database table called and use the single table inheritance mechanism of Rails. Charges add to the order total, and credits work in the opposite direction.
Orders have one or more adjustments associated with them and each adjustment also belongs to an adjustment source. This allows charges and credits to recalculate themselves when requested. Adjustments are always recalculated before they are saved which includes every time and order is updated. This provides a very flexible system by which an adjustment can determine that it is no longer relevant based on changes in the order.
Consider a coupon that takes $5 off all orders over $20. If the order exceeds the required amount during checkout the coupon will create the proper adjustment. If the customer then decides to edit their cart (before completing checkout) then you will want to make sure that the coupon still qualifies. If the order total drops below the required amount the source of the adjustment (in this case the coupon) will have the ability to remove the adjustment based on its own internal logic.
WARNING: There are significant changes to the database to support the new adjustment system. The migrations should update your legacy data and create the necessary tax and shipping adjustments for existing orders but you should backup your database before running.
Spree now supports a flexible coupon system. Coupons in an online store are virtual and can be thought of as “codes” that must be entered during the checkout process. Coupons serve two important functions. First, they determine whether or not they are eligible to be used for the offer in question. Second, they calculate the actual credit/discount that should be applied to the specific order (assuming that the eligibility requirement is satisfied.)
Coupon eligibility is completely customizable on a per coupon basis. Eligibility is determined by the following factors.
- Start Date – coupons can be configured to be invalid before a specific date
- Expiration Date – coupons can be configured so that they are not usable passed a certain date
- Expiration Date – coupons can be configured so that they are not usable passed a certain date
- Number of Uses – coupons can be restricted to an arbitrary number of uses (typically a single use if there’s a limit at all)
- Combination – there is an option to restrict specific coupons so that they cannot be combined with other coupons in the same order.
Any other restriction on eligibility is intended to be provided by custom calculators. The method has access to the complete order (including shipping and other related information) and can simply return if the coupon is not to be applied in a specific situation
INFO: The next version of Spree will also provide built in filtering for coupons based on product properties and taxon information. This will provide a standard way to restrict coupons to certain types of products. As a workaround, you can accomplish this by hard coding restrictions in your calculator.
The method in is responsible for the actual calculation of the credit to be applied for the cooupon. By default, Spree will not allow the credit amount to exceed the item total. The credit adjustment associated with a coupon is subject to recalculation based on changes in the order. This is no different then any other adjustment to the order total (such as shipping or tax charges.)
There have been several minor but crucial changes to the checkout process. The primary motivation for these changes was to improve maintenance of the checkout process and to simplify checkout customization.
Prior to the refactoring, much of the checkout logic was contained in . The idea was to isolate this logic from the and to make it easier to extend. In this release we have just taken this another step further and made the checkout its own resource.
The views have been shuffled around a bit due to this refactoring. This shouldn’t affect you too much unless you have an existing Spree application in which you customized some of the checkout partials. For instance, has been moved to . So you may need to
rename your custom partials if you have any.
For more detailed information on the nature of these changes, please see the relevant commit in Github.
Some changes have been made to allow you to attach images to both the Product model and each individual variant for a product. The Images administration has been relocated from the main product details form to it’s own tab accessible via the right hand side bar on the product details screen.
This new admin interface enables you to select from a drop-down list which object (product or variant) the image represents. Note if a product does not contain any variants then the drop-down is not displayed to ensure that basic implementations are not cluttered with unnecessary administration options.
The front-end product details interface has also been updated to filter the displayed images depending on which variant is selected, and the cart view now displays the image of the selected variant.
We’ve upgraded the paperclip gem to take advantage of recent changes. Paperclip is the library which handles creation of and access to the various formats of image. On top of this, we’re explicitly catching errors
in the image creation stage and returning these via the validation mechanism – also adding a more
meaningful message in the list. This will avoid the silent failures that some people have experienced when they don’t have image magick installed correctly.
Another change is to store the original image’s width and height: this info is sometimes useful when
working with a set of images with different ‘shapes’, e.g. where your images might all have a width of 240 but (minor) variation on height. Knowing the height of the original allows you to calculate the max height of your images and thus to create a suitable bounding box.
Finally, note that the processing tools behind paperclip can do many transformations on the images,
such as cropping, color adjustment, … – and these can be requested by passing the options to
paperclip, or you can run the conversions on a batch of images in advance of loading into Spree.
Automatic cropping is particularly useful to make best use of screen area.
Spree now runs with version 2.1.13 of SearchLogic. It has meant some minor recoding of how searches
are set up and paginated, and allowed some of the existing forms to be simplified (by taking advantage
of new functionality) and opened the door to more sophistication in selecting products, e.g. for
handling faceted search or product groups.
To make it easier to construct sets of products for various uses, we’ve added some more named scopes which
help with taxon, property, and availability of option values. The first kind ( and
) allows restriction to a set of taxons and their combined descendents. The property
scope takes a property object (or its id – the definition uses Rails’ automatic conversion)
and an optional argument for uniquifying the table names in complex queries, eg where you are filtering by
two distinct properties. This scope does not take a property value: the design is that you add further
condition(s) on the value in a subsequent scope. It will handle cases where the property is absent or null
for a product. There is a simpler scope for simpler cases.
The option type scope (, with its prerequisite ) follows the pattern
of option type object or id, and an optional table name, and is intended as a basis for further conditions
on the value of that option type.
See for the definitions, and see for examples of
It is often useful to cut down the results in a taxon via certain criteria, such as products in a price
range or with certain properties, and sometimes you want a set of restrictions selectable via checkboxes
Using ideas from SearchLogic version 2, Spree now contains a basic framework for this kind of filtering.
You can some basic filtering by visiting (unless you have overridden the products
controller), where it allows you to select zero or more of a taxon’s children and to select some price ranges and product brands.
File explains the mechanism in detail, with several concrete examples. Basically,
a filter definition associates a named scope with a mapping of human readable labels to internal labels.
The named scope should be defined to test the relevant product attribute(s), and to convert a set of these
internal labels into tests on the attributes. For example, you may want to filter by price range, so
should set up labels for price ranges like 0-20, 20-50, 50-100, 100 or more; then define a named scope
which maps these into a combined test on the (master) price attribute of products.
The partial displays a checkbox interface for the filters
returned by the method for the selected taxon. This method allows you to control
which filters are used for some taxon, eg a filter on fabric type may be required for clothing taxons,
but not suitable for mugs etc.
To use this framework, you should override and extend and define a suitable
method for taxons.
The new named scopes (above) are useful building blocks for adding application-specific filters.
Spree now saves the last used bill and ship addresses for logged in users and uses these as the defaults
in their next checkout. If the ship or bill addresses are edited in checkout, then the old addresses are
left unchanged and new addresses saved as the defaults. This is a very simple form of address book.
It is now possible to include initializers in your extensions. This makes it a lot easier to
configure extensions and to make site-specific customizations, and to keep them with the relevant
If a method for a controller, Spree will pass all requests for invalid objects to
this method. This provides an easy way for applications to add specific handlers for invalid requests.
For example, you may wish to direct customers back to the front page.
If no method has been defined, Spree will use its default 404 response.
The checkout code is now more careful about returning and checking results from key operations, and
a few more handlers for exceptions and invalid responses have been added. In normal use these should
not occur, but they may sometimes occur if you have an error in your database or configuration.
The task has been eliminated. It turns out there were some crucial flaws that caused issues when the older version of Spree used a different version of Rails or a different version of than the newer version of Spree. The rake task has been replaced by a new gem command:spree —update
You can also use the abbreviated form:spree —u
After installing a new version of the Spree gem, simply run either one of these commands from inside (your application directory) and your application will be upgraded.
The update process is also now less “destructive” than in previous versions of Spree. Instead of silently replacing crucial files in your application, Spree now checks the content of files it needs to replace, and if the old version differs, it will be saved with a suffix.
This makes it easier to see when and how some file has changed – which is often useful if you need to update a customized version. The update command will also no longer copy the file – the original version just loads the core Spree routes file, so has no need to change. (Recall that you can define new routes in your extensions.)