Setup Rails 4.1, Spring, Rspec, and Guard

Rails 4.1 allows us to use Spring to run our rails and rake commands quickly by running your application in the background and avoiding the rails startup time penalty. It took me a little while to find this information, so here is my guide to setting this up.

I’m using the Rspec testing framework with the Guard event watcher as the test runner. Spring allows us to watch the test run almost immediately after hitting save of a file in the editor.

First, let’s start with a fresh app to understand things. Upgrading an existing app is straightforward with this technique as well. Note that I am using Rails 4.1.0.beta1 on Ruby 2.1.0p0.

1
2
3
% rails new myapp -T
% cd myapp
% vim Gemfile

After we open the Gemfile in our editor, we add the following gems:

  • rspec-rails - The RSpec testing framework with Rails integrations
  • spring-commands-rspec - Adds rspec command for spring. Includes a dependency for the spring Rails application preloader.
  • guard-rspec - The Guard file watcher for running rspec
  • rb-fsevent - For OS/X only, waits for file changes from the Mac OS/X FSEvents API instead of polling the disk for changes.

Add this block to the Gemfile (You may wish to add gem versions as well.)

1
2
3
4
5
6
group :development, :test do
  gem 'spring-commands-rspec'
  gem 'rspec-rails'
  gem 'guard-rspec'
  gem 'rb-fsevent' if `uname` =~ /Darwin/
end

“Bundle” again after saving to install the dependent gems.

1
% bundle install

Setup Spring

The spring command runs a command through the spring application runner. By default, it is configured to run rails and rake commands only. We added a plugin gem to allow it to run rspec for us.

Spring has a binstub subcommand that updates the scripts in myapp/bin to load the spring runner. Run this command to configure these scripts (when converting to spring) and for the rspec command.

1
2
3
4
% spring binstub --all
* bin/rake: spring already present
* bin/rspec: generated with spring
* bin/rails: spring already present

You can check if spring has your application running as a background process with the status subcommand. When you run a spring-enabled command, it will start the server.

The startup for the first time will take a moment as rails initializes. Now that spring has started the app server for you, subsequent runs will use a forked process from this server instead and return faster.

1
2
3
4
5
6
7
8
9
% spring status
Spring is not running.
% rails g
...
% spring status
Spring is running:

89168 spring server | myapp | started 5 secs ago
89170 spring app    | myapp | started 5 secs ago | development mode

The spring server will shutdown automatically when your shell session is closed. You can shut it down yourself by:

1
2
% spring stop
Spring stopped.

That’s about all you need to know to get started with spring.

Setting up Rspec and Guard

This process is the same as you normally would do:

1
2
3
4
5
6
7
8
% rails g rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
% guard init
11:32:14 - INFO - Writing new Guardfile to /Users/allen/src/myapp/Guardfile
11:32:14 - INFO - rspec guard added to Guardfile, feel free to edit it
% vim Guardfile

This sets up the files for rspec and guard. Now we have to tell guard to use the spring runner when using rspec. Edit your Guardfile and change the command for rspec to spring rspec. Change this line:

1
guard :rspec do

to

1
guard :rspec, cmd:"spring rspec" do

Running

(Running with binstubs, shell extensions, alias, etc. may make executing these commands different on your system. You may need to bundle exec rails or bin/rails, or however your environment is setup.)

Check out the time gains running rspec through spring, I’ll use the time command:

1
2
3
4
5
6
7
% time spring rspec
...
spring rspec  0.12s user 0.07s system 6% cpu 3.126 total

% time spring rspec
...
spring rspec  0.12s user 0.06s system 30% cpu 0.600 total

This is on a minimal app with a single, scaffolded resource. As your app grows larger, the initial startup time will be longer, and your time savings will multiply accordingly. (Of course, you can just run the spring rspec command if you are more interested in the results rather than the timings.)

To start TDD’ing, fire up guard in a terminal session.

1
2
3
4
5
% guard
11:48:02 - INFO - Guard is using TerminalTitle to send notifications.
11:48:02 - INFO - Guard::RSpec is running
11:48:02 - INFO - Guard is now watching at '/Users/allen/src/myapp'
[1] guard(main)>

This runs guard to watch your app files and kicks off the spring rspec command to run your changed spec file or suite.

If you need to change something basic in your app, such as adding a gem, updating a local dependency that could be cached, you need to restart both guard (Ctrl-D at the console) (or a server or console process), and spring (spring stop). Restarting guard will restart spring as well, with your dependencies reloaded.