Extensions
NOTE: Spree Extensions are a brand new feature just recently added to the source code. They are scheduled to be released in late May 2008 and may contain minor issues until this time.
Spree now supports a powerful extension mechanism. This allows us to focus on our mission of building a solid foundation that addresses 90% of the commerce problem. Extensions address the remaining 10%. Extensions provide a logical and consistent way for Spree users to supply any missing functionality in their application. Extensions are designed in a way that should be highly intuitive to the experienced Rails programmer. They also provide a convenient way for users to develop and share extensions with other members of the Spree community.
The Spree extension mechanism was based extensively on the work of the Radiant community. The Radiant CMS project has a very similar design philosophy (“no fluff”) and has already solved the problem in a very elegant fashion.
Overview
Custom extensions should be placed in the vendor/extensions directory of your project. Extensions placed in this directory will be automatically available to your application. What does an extension allow you to customize? The short answer is pretty much everything.
- Models
- Views
- Controllers
- Routes
- Migrations
- Rake tasks
Some of the more obvious possibilities would be to override the default view or controller used by Spree. Most stores will need to customize the UI and you can use extensions to do this. You can also use an extension to mixin functionality into an existing controller or view. Since extensions have their own migrations you can modify existing Spree tables or create new ones in your database. The possibilities are almost endless.
Directory Structure
Extensions have a directory structure that should look very familiar to you. They follow essentially the same layout as a standard Rails app.
app controllers helpers models views db migrate lib spec controllers helpers models spec.opts spec_helper views
So even though your Spree application will not have an app directory, your extensions will. If your primary goal is to simply customize Spree for a specific business then you could just create a single extension and put all of your custom stuff in there. If you would like to reuse stuff between your own projects, or even share them with the Spree community, then you will want to organize your work logically into multiple self-contained extensions.
I18n
Tutorial
There is a very detailed extensions tutorial that will explain how to create your own extensions.
Available Extensions
There are numerous extensions that have been written for Spree. We’ve attempted to consolidate the list of known extensions on the Extensions Listing page for your convenience.
Tips and Tricks
Adding Variant Fields
You may be interested in adding one or more fields to the variant model using an extension. There is an additional_fields variable that is populated in admin/variants_controller.rb. Any new fields that are added to the variant table by an extension are automatically picked up in the list and edit views.
This is a superior approach to simply overriding the views in your extension. The advantage to this approach is that multiple extensions can add columns to the variant model without having the clash of views.
Extension Migrations
Extensions have a special migration script (script/generate extension_migration <extension_name> <migration_name>) that allows you to add migrations with the appropriate timestamp to your extension.
Modifying the Checkout Workflow
Its possible for an extension to modify the state machine used to model the checkout process. One example of how this is done can be found in the shipping extensions that ships with Spree. This extension basically changes the default flow of address -> payment to address -> shipping -> payment.
Order.state_machines['state'].events['next'].transitions.delete_if { |t| t.options[:to] == "creditcard_payment" && t.options[:from] == "address" }
Order.state_machines['state'].events['next'].transition(:to => 'shipment', :from => 'address')
Order.state_machines['state'].events['next'].transition(:to => 'creditcard_payment', :from => 'shipment')
Order.state_machines['state'].events['previous'].transition(:to => 'address', :from => 'shipment')
Order.state_machines['state'].after_transition :to => 'shipment', :do => :before_shipment
Order.state_machines['state'].events['edit'].transition(:to => 'in_progress', :from => 'shipment')
New steps in the checkout process should always add an edit transition so that the “view cart” link will continue to function properly.
Using Migrations for Custom Configurations
Spree comes with all sorts of default configurations that you will likely want to customize. Many of these values can be changed now through admin screens (those that can’t be changed will be able to shortly once those screens are written.) Once a preference is changed from its default, the value is stored in the database.
It is possible to use a migration to setup these preferences so that you can set the preferences of your site automatically. This is handy when migrating a new series of configurations from a tested development environment to production. You no longer have to remember to manually change these settings, just run the migrations like normal.
For example, the default country in Spree is United States. If you wanted the default country to be Ireland you could add the following to your site extension:
class AddCustomConfigurations < ActiveRecord::Migration
def self.up
Spree::Config.set(:default_country_id => 96)
end
def self.down
end
end