Upgrade Notes

General upgrade process

Back up your database and code

Always advisable!

Perform the standard upgrade command

spree —update

Remove obsolete initializers

rm -rf config/initializers/compass.rb

h5. Remove defunct contents of public dirs

rm -rf public/javascripts/
rm -rf public/stylesheets/
rm -rf public/images/

Take note of existing payment gateway settings

The new payment gateway implementation will remove existing settings, and these need to be added again using the new interface.

Run the migrations

rake db:migrate

Configure a payment method

See the additional information later in the release notes.

Deprecation Warnings

The newer version of Rails used by Spree generates a lot of deprecation warnings. You may see the following message in your console:

DEPRECATION: require "activerecord" is deprecated and will be removed
in Rails 3. Use require "active_record" instead.

Remove all instances of require 'activerecord' from your Rakefiles

API Changes

Change to taxonomies variable

Taxonomies used to be set in most shared views. Now, it is only set after calling get_taxonomies (inherited from Spree’s base controller).

Spree Base Controller and Layouts

Spree::BaseController inherits directly from ActionController::Base, rather than from ApplicationController (which itself is now an empty class to help interaction with other Rails apps). If you used app/views/layout/application.html.erb in an extension. e.g.

Spree::BaseController.class_eval { layout 'application' }

… then you will need to rename it to spree_application.html.erb and update the occurrences.

Adding admin tabs changed

extension_tabs is no longer used, instead use theme “hooks”:hooks.html.

Theme Support

Spree now has basic support for theming. Themes in Spree are implemented as “extensions”:extensions.html. All of the default views in Spree have now been abstracted into a default theme. You can override all or parts of the default theme in a new theme. Themes have their own generator and are created as follows:

script/generate theme foo

You can read more about themes in the very extensive customization guide

Don’t panic if you have already customized Spree views in your site extension for a previous release of Spree. These view customizations should continue to work as long as they are loaded after the default theme extension.

Named Scopes and Product Groups

In various applications, we need to create lists of products according to various criteria, e.g. all products in taxon X, or all products costing less than $20, or composite criteria like all products costing more than $100 that have brand Y. Spree provides several so-called named scopes, which provide filtering by various aspects of the basic data, some of which can be chained or composed together for more complex filters.

Named scopes can also be combined. The following chain of scopes lists the products that are active and with a price between $18 and $20.

Product.active.price_between(18,20)

Product groups allow for the defining and naming groups of products for various purposes in an application. For example, you can define a group called Ruby products which contains everything with Ruby in the product name, or another group called Ruby clothing which is the sub-list of the above limited to items in the Clothing taxon. Product group definitions can also take price ranges, product properties, and variant options into account. It is possible to add your own filters by defining new named scopes too.

Please see the documentaiton for a more complete explanation of named scopes and product groups.

Improvements to Payment Gateway Configuration

This release contains significant improvements to how payment gateways are configured. Gateways are no longer supported by database migrations, this scheme has been replaced by Active Record models that extend Gateway. The configuration of gateways is now done through standard Spree preference configuration. The documentation has also been updated and contains a more detailed explanation.

One major improvement is that it is now possible to configure multiple gateways for each of your Rails environments. Its also possible to use the live production server in development mode when previously, you were required to run in test mode. One unfortunate side effect of this improvement is that your existing gateway configuration information will be lost and you will need to reconfigure your gateway in the admin interface.

You should make a note of your gateway configuration setting before upgrading since you will need to reconfigure your gateway when you’re done.

This approach to implementing and configuring gateways is extremely flexible. It makes it trivial to implement a new gateway that is already supported by Active Merchant. There are other useful benefits to this approach that a developer may be interested in knowing.

Support of Non Active Merchant Gateways

This architecture allows Spree to support gateways that are not officially supported by Active Merchant. Many times a new gateway is donated by someone in the community but its languishing in the queue waiting for someone to test and accept the patch. You have the option of taking that code (or writing your own from scratch) and implementing it within Spree. Instead of delegating to an Active Merchant class, you can simply implement that functionality yourself. You could also include the new gateway code from an Active Merchant fork inside your implementation and delegate the standard authorize, capture, etc operations to it.

Ability to “Patch” Active Merchant Gateways

We’ve noticed that sometimes it takes a while for a crucial Active Merchant patch to be applied. That’s certainly understandable, the Shopify guys have a business to run and its probably not a high priority for them to make sure that the latest obscure gateway patch is applied in a timely fashion. Fortunately, the Spree approach to wrapping these gateways provides you with a convenient option.

Lets say there is a bug with the +authorize+ method. You could simply provide an implementation of the gateway that has the patched version of the authorize method and then delegates to the Active Merchant class for everything else (since that works just fine.)

Additional Functionality Beyond Active Merchant

Another benefit of the architecture is that it makes it possible for Spree to provide additional common functionality that was not envisioned by Active Merchant. Specifically, it is possible to provide an abstraction for storing credit card profiles to be used with recurring payments. There’s a good reason for Active Merchant to not care about this functionality. Its designed for people who just want to drop a single gateway provider into their application. Most programmers don’t need three different gateways at once. Spree is a specialized use case. Its providing multiple gateways for you to choose from and so its desirable to have a standard method for operations such as this.

Recurring payments are not yet supported in Spree although there are plans to provide this in the near future.

Multi Step Checkout

Checkout Steps

Spree has returned to a multi step checkout process. The following checkout steps are defined by default.

  • Registration (Optional)
  • Address Information
  • Delivery Options (Shipping Method)
  • Payment
  • Confirm

There is also a default progress “train” which shows the current step and allows you to jump back to a previous step by clicking on it.

If you have a site running on a previous verison of Spree, your checkout process will likely need to be upgraded. The good news is the new approach is much easier to customize.

The checkout process is highly customizable - in fact, this is the reasoning behind moving away from the single step checkout. There is far less code hidden in javascript and each checkout step has its own partial. See the checkout documentation for mor information on how to customize the checkout.

Countries Available for Shipping and Billing

The mechanism for determining the list of billing and shipping countries has changed. Prior to this release, there was no way to limit the billing countries and shipping countries were limited by the countries included in the shipping zones that were configured. The new approach is to simply use all countries defined in the database by default.

The list can be limited to a specific set of countries by configuring the new :checkout_zone preference and setting its value to the name of a zone containing the countries you wish to use. This should handle most cases where the list of billing and shipping countries are the same. You can always customize the code via extension if this does not suit your needs.

State Machine

The Checkout model now has its own state machine. This allows for easier customization of the checkout process. It is now much simpler to add or remove a step to the default checkout process. Here’s an example which avoids the address step in checkout.

class SiteExtension < Spree::Extension
  def activate
    # customize the checkout state machine
    Checkout.state_machines[:state] = StateMachine::Machine.new(Checkout, initial: 'payment') do
      after_transition to: 'complete', do: :complete_order
      before_transition to: 'complete', do: :process_payment
      event :next do
        transition to: 'complete', from: 'payment'
      end
    end

    # bypass creation of address objects in the checkouts controller (prevent validation errors)
    CheckoutsController.class_eval do
      def object
        return `object if `object
        `object = parent_object.checkout
 unless params and params[:coupon_code]

`object.creditcard ||= Creditcard.new(month: Date.today.month, year: Date.today.year)
        end
        `object
 end
 end
 end
end

Controller Hooks

The*CheckoutController+ now provides its own “hook mechanism” (not to be confused with theme hooks) which allow for the developer to perform additional logic (or to change the default) logic that is applied during the edit and/or update operation for a particular step. The Spree::Checkout::Hooks module provides this additional functionality and makes use of methods provided by the resource_controller gem. See the checkout documentation for further details and examples.

Checkout Partials

The default theme now contains several partials located within vendor/extensions/theme_default/app/views/checkouts. Each checkout step automatically renders the edit.html.erb view along with a corresponding partial based on the state associated with the current step. For example, in the delivery step the _delivery.html.erb partial is used.

Javascript

Spree no longer requires javascript for checkout but the user experience will be slightly more pleasing if they have javascript enabled in their browser. Spree automatically includes the checkout.js file located in the default theme. This file can be replaced in its entirety through use of a site extension.

Payment Profiles

The default checkout process in Spree assumes a gateway that allows for some form of third party support for payment profiles. An example of such a service would be Authorize.net CIM. Such a service allows for a secure and PCI compliant means of storing the users credit card information. This allows merchants to issue refunds to the credit card or to make changes to an existing order without having to leave Spree and use the gateway provider’s website. More importantly, it allows us to have a final “confirmation” step before the order is processed since the number is stored securely on the payment step and can still be used to perform the standard authorization/capture via the secure token provided by the gateway.

Spree provides a wrapper around the standard active merchant API in order to provide a common abstraction for dealing with payment profiles. All Gateway classes now have a payment_profiles_supported? method which indicates whether or not payment profiles are supported. If you are adding Spree support to a Gateway you should also implement the create_profile method. The following is an example of the implementation of create_profile used in the AuthorizeNetCim class:

# Create a new CIM customer profile ready to accept a payment
def create_profile(creditcard, gateway_options)
 if creditcard.gateway_customer_profile_id.nil?
 profile_hash = create_customer_profile(creditcard,
gateway_options)
 creditcard.update_attributes(:gateway_customer_profile_id =\>
profile_hash[:customer_profile_id], :gateway_payment_profile_id
=\> profile_hash[:customer_payment_profile_id])
 end
end

Most gateways do not yet support payment profiles but the default checkout process of Spree assumes that you have selected a gateway that supports this feature. This allows users to enter credit card information during the checkout withou having to store it in the database. Spree has never stored credit card information in the database but prior to the use of profiles, the only safe way to handle this was to post the credit card information in the final step. It should be possible to customize the checkout so that the credit card information is entered on the final step and then you can authorize the card before Spree automatically discards the number while saving the Creditcard object.

Seed and Sample Data in Extensions

Seed data is data that is needed by the application in order for it to work properly. Seed data is not the same as sample data. Instead of loading this type of data in a migration it is handled through the standard rails task through rake db:seed. The rake task will first load the seed data in the spree core (ex. db/default/countries.yml.) Spree will then load any fixtures found in the db/default directory of your extensions. If you wish to perform a seeding function other than simply loading fixtures, you can still do so in your extension’s db/seeds.rb file.

Sample data is data that is convenient to have when testing your code. Its loaded with the rake db:sample task. The core sample data is loaded first, followed by any fixtures contained in the db/sample directory of your extensions.

If you have fixtures in your extension with the same filename as those found in the core, they will be loaded instead of the core version. This applies to both sample and seed fixtures. This allows for fine grained control over the sample and seed data. For example, you can create your own custom sample order data in your site extension instead of relying on the version provided by Spree.

You should remove all db:bootstrap tasks from your extensions. The new bootstrap functionality in the core will automatically load any fixtures found in db/sample of your extension. Failing to remove this task from your extension will result in an attempt to create the fixtures twice.

RESTful API

The REST API is designed to give developers a convenient way to access data contained within Spree. With a standard read/write interface to store data, it is now very simple to write third party applications (ex. iPhone) that can talk to Spree. The API currently only supports a limited number of resources. The list will be expanded soon to cover additional resources. Adding more resources is simply a matter of making the time for testing and investigating possible security implications. See the REST API section for full details.

Inventory

Inventory modeling has been modified to improve performance. Spree now uses a hybrid approach where on-hand inventory is stored as a count in Variant#on_hand, but back-ordered, sold or shipped products are stored as individual InventoryUnits so they can be tracked.

This improves the performance of stores with large inventories. When the on_hand count is increased using Variant#on_hand=, Spree will first fill back-orders, converting them to InventoryItems, then place the remaining new inventory as a count on the Variant model. A migration is in place that will convert on-hand InventoryItems to a simple count during upgrade. Due to an issue with the sample data, demo stores cannot be upgraded in this fashion and should be re-bootstrapped.

Miscellaneous improvements

Sample Product Images in Extensions

For some time now you’ve been able to write sample data fixtures in extensions that will get run when you load sample data with the rake db:bootstrap task.

Now you can also add sample product image files in your extensions in the extensions own lib/tasks/sample/products directory. These images will be copied to the public/assets/products directory when the sample data is loaded.

Additional information on the release can be found in the CHANGELOG file as well as the official ticket system.

Ruby 1.9 Support

Spree is now 100% Ruby 1.9 compatible. There are a few workarounds needed to achieve this and those are consolidated in a custom initializer appropriately named workarounds_for_ruby19.

Sales Overview

The default admin screen now shows a series of tables and graphs related to recent sales activity. By consulting this screen you can now see the following information

  • Best Selling Products
  • Top Grossing Products
  • Best Selling Taxons
  • Information on the Last 5 Orders
  • Biggest Spenders
  • Out of Stock Products
  • Order Count by Day

Extension Load Order

It is now recommended to define the extension load order outside of the environment.rb file. This makes it easier for you to use the standard environment.rb file that comes with Spree and thus easier to upgrade. To define the extension load order inside of an initializer you can use the following line of code:

SPREE_EXTENSIONS_LOAD_ORDER = [:theme_default, :all, :site]

SEO Improvements

Products and taxons are now available by a single URL only. Prior to this release both of these URL’s returned the same result:

  • http://localhost:3000/products/ruby-on-rails-ringer-t-shirt/
  • http://localhost:3000/products/ruby-on-rails-ringer-t-shirt

Now we are returning a 301 redirect for the version of the URL without the trailing ‘/’ character. Some SEO experts seem to feel that inconsistent links and links without a trailing slash can be penalized We’ve been asked by one of our clients to fix this. We’re passing on the SEO improvements to you!

Multiple Forms of Payment

Spree now supports multiple forms of payment. This support is in the early stages but the basic build blocks are now present so that it should be quite easy to allow additional forms of payment. More documentation and improvements in this area are coming.

Refunds and Credits

Spree now has explicit support for refunds and credits. More details to follow.

Known Issues

The ticket system lists all known outstanding issues with the Spree core. Some issues have a release target (milestone) attached: this is an indication of how soon an issue will be tackled.

There are some problems which we have traced to other projects. We list a few significant ones here.

Ruby 1.9 and Sqlite3

This combination doesn’t work with Rails 2.3.5: the change_column calls make all fields into NOT NULL. See the related ticket for more info.

Workaround: apply the Rails patch by hand, or use MySQL instead if you want to try Ruby1.9