
Spree is without a doubt a de-facto eCommerce stack of Ruby world. Yet to many Spree is still a pandora box. In this tutorial, I will try to go through step by step from how to set up a Spree sandbox app on a local box to deployment to Heroku.
Please note that all instructions are written for Apple MacOSX 10.7.x system. However I believe it applies to other UNIX and Linux systems too (maybe with minor adaptations).
Prerequisites
Heroku
Install Heroku toolbelt via Rubygems:
1
| |
If you have installed Heroku, please ensure you update to version 2.1.0 or higher for Cedar support:
1 2 3 | |
Ruby
By default, Heroku Cedar stack uses Ruby 1.9.3. And normally it is always the latest minor version, so it is recommended you to install the latest version on your local box:
1
| |
I use RVM to manage rubies versions on my box, you can adapt this technique if you use rbenv or precompiled binary package
Spree
1
| |
Check installed spree gems:
1 2 3 4 5 6 7 8 9 | |
spree gem consists of many components, however please note that you only need spree_core
to build an online store.
PostgreSQL
Heroku only supports PostgreSQL. It is a good practice to have you development environment use the same DB.
PostgreSQL can be installed on OSX with either of these methods below:
1. Postgres.app (RECOMMENDED)
You can install the Postgres.app from Heroku guys at http://postgresapp.com/
2. Homebrew
If you aren’t in a rush, PostgeSQL can be installed with Homebrew:
1
| |
Though I do not recommend this method because you might bump into issues with compilation. Please make sure you read the Build Notes after the installation.
pg gem
Now we need to install pg gem too:
1
| |
ImageMagick
Spree uses paperclip gem which in turn require imagemagick. You search on Google
for binary DMG package or for my case, I install it with Homebrew:
1
| |
Prepare local application
Create a new rails app default to postgreSQL
1
| |
Configure database setting by editing config/database.yml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
then create the DB tables:
1
| |
Bootstraping on local box
There are two ways to bootstrap Spree, I prefer the latter method as it gives me more control of bootstraping process.
Both ways runs Asset Precompiling rake task which fix an issue where Heroku could not precompile asset, you could read more about this issue at Assets Precompiling section
1. Wizard mode
spree_cmd gem provides the convenient spree command that add the Spree gem, create initializers, copy migrations and optionally generate sample products and orders.
1
| |
You can notice that I explicitly declare RAILS_ENV=development here. If not,
spree install will assume your RAILS_ENV=production
The wizard will guide you through a list of questions, I opt no for Default Gateway
because I am not going to use skrill gateway for this tutorial.
1 2 3 4 5 6 | |
if nothing goes wrong, you would see:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
2. Manual mode
You could manually append spree gem into the end of your Gemfile:
1
| |
If you have not yet run bundle install, please run it now:
1
| |
Next we invoke Spree install generator to copy migrations, initializers and generate sample data:
1
| |
OR
Bootstraping manually with command:
1 2 3 4 | |
Once the bootstrap is finished, we need to precompile our assets too:
1
| |
Deploy to Heroku
Configure web server
By default, Heroku use the thin webserver. However in this tutorial, we are going to
use puma instead, just to show you the great new process types system that
Cedar support.
Append to Gemfile:
1 2 3 | |
and install the gem with:
1
| |
The great thing about Cedar stack is that Heroku introduces a new way to scale your app,
that is Process Model, now you could define a custom list of process type
that you want to run in the Procfile file.
We configure our unicorn which is of type web by creating new file in Rails.root
folder Procfile:
1
| |
Assets Storage
Because Heroku is disk-less therefore assets like images are not persistently stored. The workaround is to use Cloud storage service like Amazon S3.
spree-heroku extension
The spree_heroku gem lets you store images and data to Amazon S3, to install it
we append to Gemfile:
1
| |
then
1
| |
Next, we create a new bucket ‘fool-man-chew_production’ under US Standard region via AWS Management Console.
We need to tell Spree how to access our bucket, there are 2 ways to configure S3 settings.
First one is to create Heroku config vars (recommended way):
1 2 3 | |
The second is to create a new file under config/s3.yml and modify the key in accordance to your S3 account:
1 2 3 4 | |
Heroku boostrap
We are going to create an Cedar stack app:
1
| |
If success, you would see below output:
1 2 3 | |
and double check git remote you would see heroku remote listed:
1 2 | |
Add SSL certificate
Spree production mode always enforce SSL. This step is very optional, please read Disable SSL in Production section if you want to disable SSL in Production mode.
A Piggyback SSL is a now standard feature on all Heroku apps so you don’t have to enable. We are not going to buy a certificate for this test app. Instead, we are going to set up a Self-Signed SSL Certificate.
A private key and certificate signing request can be generated:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
and now the self-signed SSL certificate is generated from the site.key private key and site.csr files:
1
| |
The final.crt file is your site certificate suitable for use with Heroku’s SSL add-on along with the site.key private key.
Now we upload those two files to Heroku:
1 2 | |
Deploy Spree to Heroku
Now we could push our app to Heroku:
1 2 3 4 | |
OPTIONAL: If you ever bump into issues where Bundler fails to locate gems, the best workaround is to cache the bundle:
1 2 3 | |
If all goes well, you would see following output:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Next we could repeat the same bootstraping step on our remote heroku:
1
| |
Now we could open app:
1
| |
However to your surprise you could see that there are no images displayed correctly. This is expected behavior and worry not, I have your back covered, please read section Assset Pipeline
Assets Precompiling
Heroku would fail precompiling assets in slug compilation. Following output show the error:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
It make some sense though because Spree requires access to DB to complete this task and yet before you push to Heroku the environment config is not present.
So we have to disable precompile on initialization by set config.assets.initialize_on_precompile to false in config/application.rb
1
| |
To workaround this issue, there are 2 ways:
1. Locally Precompiling Assets
We precompile the assets on localbox:
1
| |
What will happen next is Sprocket will compile our assets and place them in public/assets folder. What Heroku really care is the public/assets/manifest.yml. This file contains all MD5 checksums of our assets and Heroku will check the existence of the file to tell if we compile our assets locally or not. Make sure you double check your .gitignore and remove the public/assets if there is one so git won’t omit this path.
If we push this file to our server:
1 2 3 | |
you would see:
1 2 3 4 | |
You could read more on Rails 3.1 on Heroku
Again, I do not recommend you using this method, because you pollute your source tree with precompiled assets. Please avoid this at all cost and instead use a CDN like S3 or Rackspace to serve our precompiled assets.
2. Serve precompiled assets on CDN (RECOMMENDED)
First, we install asset_sync gem by appending to your Gemfile:
1 2 3 4 | |
then
1
| |
Then we have to enable user_env_compile plugin first:
1
| |
Next, we configure asset_sync to sync with Amazon S3 by adding following variables into Heroku env:
1 2 3 4 5 6 7 8 9 | |
Configure config/environments/production.rb to use Amazon S3 as the asset host and ensure precompiling is enabled:
1
| |
Also, ensure the following are defined (in production.rb or application.rb)
- config.assets.digest is set to true.
- config.assets.enabled is set to true.
That’s done. Commit changes and push to remote Heroku:
1 2 | |
The asset_sync override rake assets:precompile deploy task and will automatically synchronized all modified and
new assets to S3.
You should see output like below if success:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Custom Domain
Now we push a bit further by setting up custom domain for our shop, first we need to set up Heroku to respond to requests at custom domains:
1 2 | |
And inform Heroku our beautiful fool-man-chew.com domain
1 2 3 4 | |
Then I point the domain DNS to Heroku. Please read more at Heroku Custom Domain
We also need to let Spree know of our custom domain by append site_url in our
config/initializers/spree.rb
1 2 3 | |
Add, commit and push again:
1 2 3 4 | |
Extra
Disable SSL in Production mode
Edit file config/initializers/spree.rb:
1 2 3 | |
Make sure you commit the changes to app repository.
Deploy to Heroku using heroku_san
It is much quicker to setup and deploy to Heroku by using heroku_san gem.
Simply install heroku_san by appending to your Gemfile:
1 2 3 | |
then
1
| |
Configure heroku_san by creating config/heroku.yml file with content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
We deploy to heroku by running following rake task:
1
| |
Conclusion
Spree 1.0 is a big major leap. It is faster, more robust and much easier to install. Outstanding issue such as ‘Superclass mistmach bug with Calculator::PriceBucket’, ‘Bootstraping migration run failed’ are resolved. Yet there are possibly issues that I am not aware of, so please file a ticket on GitHub Issues and I’ll make sure it has my utmost attention.
I’d like to extend my gratitude to the Spree community for the hardwork.