Overview
Spree Extensions are a way to add new functionality to your Spree store. They are a great way to extend the functionality of Spree and add new features. You can share them with Spree community on Github so anyone can use them, contribute back and share your improvements.Getting Started
Let’s build a simple extension. Suppose we want the ability to mark certain products as being on sale. We’d like to be able to set a sale price on a product and show products that are on sale on a separate products page. This is a great example of how an extension can be used to build on the solid Spree foundation. Run the following command from a directory of your choice outside of our Spree application:spree_simple_sales
directory with several additional files and directories. After generating the extension make sure you change to its directory:
Adding a Sale Price to Variants
The first thing we need to do is create a migration that adds a sale_price column to variants. We can do this with the following command:db/migrate/XXXXXXXXXXX_add_sale_price_to_spree_variants.rb
so that it contains the following:
Adding Our Extension to the Spree Application
Before we continue development of our extension, let’s add it to the Spree application. Within themy_store
application directory, add the following line to the bottom of our Gemfile
:
my_store
application.
Once you have added the gem, it’s time to bundle:
spree_simple_sales
install generator to copy over the migration we just created answer yes if prompted to run migrations:
Adding a Controller Action to HomeController
Now we need to extendSpree::HomeController
and add an action that selects “on sale” products.
Note for the sake of this example that `Spree::HomeController` is only included in spree_storefront so you need to make it a dependency on your extensions *.gemspec file.
Make sure you are in the spree_simple_sales
root directory and run the following command to create the directory structure for our controller decorator:
home_controller_decorator.rb
and add the following content to it:
sale_price
set.
We also need to add a route to this action in our config/routes.rb
file. Let’s do this now. Update the routes file to contain the following:
Viewing On Sale Products
Setting the Sale Price for a Variant
Now that our variants have the attributesale_price
available to them, let’s update the sample data so we have at least one product that is on sale in our application. We will need to do this in the rails console for the time being, as we have no admin interface to set sale prices for variants. So, in order to do this, first open up the rails console:
Decorating Variants
Let’s fix our extension so that it uses thesale_price
when it is present.
Next, create the file app/models/spree_simple_sales/variant_decorator.rb
and add the following content to it:
sale_price
present on the product’s master variant, we return that price. Otherwise, we call the original implementation of price_in
using return super
.
Testing Our Decorator
It’s always a good idea to test your code. We should be extra careful to write tests for our Variant decorator since we are modifying core Spree functionality. Let’s write a couple of simple unit tests forvariant_decorator.rb
Generating the Test App
An extension is not a full Rails application, so we need something to test our extension against. By running the Spreetest_app
rake task, we can generate a barebones Spree application within our spec
directory to run our tests against.
We can do this with the following command from the root directory of our extension:
rspec
and see the following output:
variant_decorator_spec.rb
and add the following tests to it:
price_in
method we overrode in our VariantDecorator
returns the correct price both when the sale price is present and when it is not.