Good practices in writing Spree extensions

This post is about writing extensions for Spree commerce, a “complete open source e-commerce solution for Ruby on Rails”. For those who don’t know what Spree is about, check out their official website or repository.

After reading all Spree dev guide, you will notice that Spree is really powerful, but lacks some functionality like: user reviews, user comments, internationalization, and so on. You’ll quickly notice that all of this are added by spree extensions, and possibly you are going to write one.

When writing a Spree extensions, keep in mind that other people will use them. If other devs are going to use them, initially, they will not want go trough your code. They’ll want to be end users to your extensions, installing and using it right out of the box.

Working with Spree extensions made me kind of frustrated. Almost all official extensions are good to go, but when I needed some help of the community, I freaked out. I saw repositories with just one star and more than two hundred forks!

That’s why I decided to write some “guides” to what I like to see when I check out an extension repository:

Deface listing

Spree uses deface to extend its views, allowing ERB customization without editing the view directly.

You can write some Spree defacing using two methods: writing a Deface::Override class or writing some .deface files and work with its DSL. That’s all documented on the deface repository.

To avoid confusion over which views your extension is trying to override, try to create a small list on your README file, pointing out which files you overwrote.

Examples:

Using Deface::Override

// Specify which .rb files the user should look
// Use the following filename pattern: your file should have the same name of your defacing
...
Defaces:

Frontend
* add_number_field_to_address_form.rb

Backend
* update_variation_image_to_show_sku.rb
...

Using Deface DSL

// Write the selector you defaced after naming the file that was changed
...
Defaces:

Frontend
* spree/checkout/_address.html.erb [data-hook="billing_fieldset_wrapper"]
* spree/products/index.html.erb [data-hook="search_results"]

Backend
* spree/admin/option_types/edit.html.erb #new_add_option_value
...

Tests

Write tests! Just TEST IT!.

Spree uses RSpec, so you should use it too. Spree have many helpers that can be useful, located in the spree/core/lib/spree/testing_support, since 2.0 version.

Every extension generated by Spree have a customized Rakefile that helps in the generation of a test app. This test app is an entire Rails application used for running your tests.

Testing your extension have a interesting worflow: Generate the test app with bundle exec rake test_app and run your test suite. That’s it.

You can read more about testing your extension or other Spree components here: http://guides.spreecommerce.com/developer/testing.html#testing-spree-components

Compatible Versions

Try following Spree repositories naming conventions for your versioning.

If your extension is compatible with versions 2.1.x, name that branch 2-1-stable, if compatible with 2.2.x, name it 2-2-stable and so on.

README

Write a README. Don’t just let that “Introduction goes here” hanging there. Write a simple introduction to your extension, showing what it should do and how it should do.

If your extension adds extra configurations to Spree or have some custom configurations that can be done, it is a good idea to list them in the README:

If you are using an extension configuration module

  ...
  MyExtension::Config.foo_bar = false # display foo when its true. Default: true
  ...

Or extending spree configurations

  ...
  This extension adds some preferences:

  preference :best_selling_products_shown, :integer, :default => 9
  ...

Some extra quick tips