Spree Commerce

Try It Now

Rails 3.1 Support

Posted on June 16, 2011 by Brian Quinn

Rails 3.1 adds some great new features that we’re keen to include in
Spree and some will form the basis for more theming features to
follow soon. We’re going to walk through some of these new features and
changes in this post and explain what they mean to you as Spree developers.

Those of you following along at home may have already noticed we recently pushed
a rails3-1 branch to the
Spree repository. All the details below pertain to this branch only
for now, but will be merged with master shortly and included in the upcoming Spree 0.70.0 release.

Assets Pipeline

Spree’s first Rails 3.0 based release (0.30.0) changed how extensions worked within
Spree and allowed us to adopt a standard Rails approach for supporting extension, where all extensions
became regular Rails Engines.

While engine support in Rails 3.0 was vastly improved it still had some
weak points in relation to asset and migration management that required
us to create our own approach. With the release of Rails 3.1 these weak
points have been addressed and we’re now able to remove our workarounds
and once again adopt the standard Rails approach.

All Spree generated (or upgraded) applications will now include a new
assets directory (as is standard for all Rails 3.1 apps). We’ve taken
this one step further by subdividing each top level asset
directory (images, javascripts, stylesheets) into store and admin
directories, this is designed to keep assets from the front end (store) and
back end (admin) from conflicting with each other.

A typical assets directory for a Spree application will look like:

app<br />
|— assets<br />
    |— images<br />
    |   |— store<br />
    |   |— admin<br />
    |— javascripts<br />
    |   |— store<br />
    |   |   |— all.js<br />
    |   |— admin<br />
    |       |— all.js<br />
    |— stylesheets<br />
    |   |— store<br />
    |   |   |— all.css<br />
    |   |— admin<br />
    |       |— all.css

Spree also generates four top level manifests (all.css & all.js, see
above) that require all the core extension’s and site specific stylesheets / javascripts.

Managing site specific assets

All site specific assets should be moved from the public directory into
the appropriate app/assets or vendor/assets sub-directory. All
javascript and stylesheet files in app/assets sub-directories will
be automatically included by the relevant all.(js|css) manifests.

Javascript & stylesheet files in vendor/assets sub-directories should be
manually required in the appropriate all.(js|css) manifests.

NOTE: Images will be served in development mode, or compiled into the
public directory automatically in production mode.

How core extensions (engines) manage assets

All core engines have been updated to provide four (or less) asset manifests that
are responsible for bundling up all the javascripts and stylesheets
required for that engine.

For example, spree_core provides the following manifests:

app<br />
|— assets<br />
    |— javascripts<br />
    |   |— store<br />
    |   |   |— spree_core.js<br />
    |   |— admin<br />
    |       |— spree_core.js<br />
    |— stylesheets<br />
    |   |— store<br />
    |   |   |— spree_core.css<br />
    |   |— admin<br />
    |       |— spree_core.css

These core engine specific manifests are included by default by the relevant
all.css or all.js in the host Spree application. For example,
app/assets/javascripts/admin/all.js includes:

//= require_tree .<br />
//= require admin/spree_core<br />
//= require admin/spree_promo<br />
//= require admin/spree_dash

External javascript libraries, stylesheets and images have also be
relocated into vendor/assets (again Rails 3.1 standard approach), and all
core extensions no longer have public directories.

How third party extensions should manage assets

We’re suggesting that all third party extensions should adopt the same approach and
provide the same four (or less depending on what the extension requires)
manifest files, using the same directory structure as outlined above.

Third party extension manifest files will not be automatically included in the
relevant all.(js|css) files so it’s important to document the
manual inclusion in your extensions installation instructions or provide a Rails generator to do so.

For an example of an extension using a generator to install assets and
migrations take a look at the recently added
on the rails3-1 branch of spree_wishlist.

New migration handling

We’ve also been able to retire our own custom migration handling rake
tasks in favor of the Rails 3.1 built-in equivalentes.

The following style rake tasks have been removed:

rake spree:install<br />
   rake spree:install:migrations<br />
   rake spree_core:install<br />

The new Rails equivalents are now:

rake railties:install:migrations

Which copies migrations from all engines / extensions.

To install the migrations from a single engine use:

rake railties:install:migrations <span class="caps">FROM</span>=spree_wishlist

NOTE: Migrations are copied one engine at a time, in the order that the
engine was included. All migrations are re-numbered (timestamped) with
the time they were copied. Subsequent executions of the same
rake tasks will not result in duplicate migrations as it compares the name
after the timestamp before copying.

Other changes of note

spree_site.rb no longer required

Earlier Rails 3.0 versions of Spree used to generate an application
engine file in lib/spree_site.rb, this file conflicts with recent engines
changes and has been removed.

The `activate` method that was originally housed in the file has been
replaced with a `to_prepare` block which will be automatically appended to
config/application.rb when you run the spree:site generator.

The new block will also contain the relevant require / load snippet to
include all your decorator files.

NOTE: It’s important when upgrading to remove lib/spree_site.rb and
move any logic into the new `to_prepare` block (or new intializers where

Declaring `railtie_name`

All extensions (core and third party) should now include a
`railtie_name` call inside it’s engine definition, for example from spree_wishlist:

<p>module SpreeWishlist<br />
  class Engine < Rails::Engine<br />
    engine_name ‘spree_wishlist’</p>

This is used to reference the engine by name within Rails (currently
used for installing migrations).

Call for help

The rails3-1 branch is
still pretty raw so we’ve inviting everyone to take it for a test drive
and help resolve any of the outstanding issues.

We’re logging Rails 3.1 related issues in Github

with the rail3-1 label. Please feel free to grab an issue and help out.

Also, there’s several spec and cucumber failures just waiting for your