Rails 3 Application Builders

October 6, 2010 Mike Barinek

Recently I’ve been working on a small spike intended to help jumpstart our Rails application development in the Pivotal Labs Boulder office.

Until Rails 3 was officially released, new projects used the Pivotal “rails-template” to help bootstrap development. The template is really just a GitHub repo that installs dependencies in our Rails 2 project.

There’s are few new interesting new features in Rails 3, including a “–builder=” option to the “rails new APP_PATH [options]” command. I thought this might be an interesting solution to bootstrapping an application, especially when your dependencies include Rails generators.

The spike makes a few choices regarding dependencies and testing preferences. For example, we tend to use things like RSpec and Cucumber as well as Cruise.rb, Engine Yard Cloud, and NewRelic. To make life a bit easier, I also used RVM and Gemsets to help set the initial set of dependencies. Even more interesting, I’m able to bootstrap from a GitHub Gist or any directly downloadable file URL.

Initial Setup

For everything to work without a hitch, I have both a local .rvmrc file and Bundler Gemfile within my ~/workspace/mahan directory with the below Gems installed.

[Note: I’m making an assumption here that you know and understand Bundler and RVM]

Here’s the .rvmrc file I used within the ~/workspace/mahan directory.

rvm_archflags="-arch x86_64"
rvm 1.8.7-p174@mahan

And here’s a few commands to get you started.

$ cd workspace/

$ mkdir mahan

$ cd mahan/

$ vi .rvmrc

rvm_archflags="-arch x86_64"
nrvm 1.8.7-p174@mahan"

Also, here’s the Gemfile I used within the ~/workspace/mahan directory.

You’ll need to run “gem install bundler –version 1.0” from this directory and then run “bundle install”.

source 'http://rubygems.org'

gem 'rails', '3.0.0'
gem 'mysql2'
gem "rspec-rails", '2.0.0.beta.22'
gem "rspec", '2.0.0.beta.22'
gem 'capybara', '0.3.9'
gem 'database_cleaner', '0.5.2'
gem 'cucumber-rails', '0.3.2'
gem 'cucumber', '0.9.0'
gem 'rspec-rails', '2.0.0.beta.22'
gem 'spork', '0.8.4'
gem 'launchy', '0.3.7'
gem 'jasmine', :submodules => true
gem 'json_pure', '1.4.6'

Agin, a few commands to get you started.

$ cd ~/workspace/mahan/

$ rvm gemset create 'mahan'

$ rvm gemset use mahan

$ gem install bundler --version 1.0

$ vi Gemfile

[Add the above Gemfile contents]

$ bundle install

Rails Builder

Next, I’ll dive right into the Rails command. From your ~/workspace/mahan directory run

rails new rails_example --builder=http://gist.github.com/611035.txt

The command creates a new Rails 3 application with our default set of dependencies.

Feel free to take a look at the actual Gist. You’ll notice that I extend “class AppBuilder < Rails::AppBuilder”. If you’re interested in the Rails guts, take a look around line 316 in railties-3.0.0/lib/rails/generators/rails/app/app_generator.rb. The Rails AppGenerator looks for custom builders and then performs an instance_eval on the file.

You’ll also notice that I “override” the test method within my custom AppBuilder to include RSpec, Cucumber, and Jasmine. The actual method then call the associated Rails install generator. And yes, you’ll notice we’re working on the Jasmine Rails 3 support.

def test

I also override the “leftovers” method to include things like Cruise.rb, Engine Yard Cloud, and NewRelic dependencies and configurations. The “leftovers” method gets call from the AppGenerator “finish_template” method. With a few of the “leftovers”, I simply pull the from the associated GitHub repo and copy the necessary files and/or directories.

I’ve also experiment with a Gem that includes a Thor wrapper around a custom Rails AppGenerator. The benefit for this approach is that now I’m now able include my own custom Rails options. For example

class PivotalAppGenerator < Rails::Generators::AppGenerator
  include Thor::Shell

  source_root File.expand_path('../templates', __FILE__)

  class_option :skip_rspec, :type => :boolean, :aliases => "-R", :default => false, :desc => "Skip rspec"
  class_option :skip_cucumber, :type => :boolean, :aliases => "-C", :default => false, :desc => "Skip cucumber"
  class_option :skip_jasmine, :type => :boolean, :aliases => "-J", :default => false, :desc => "Skip jasmine"

We’ll probably use a combination of the AppBuilder and AppGenerator approach, although at this time I thought some feedback would be interesting.

About the Author


Startup Recipe
Startup Recipe

If you’re thinking about starting a software project, here’s the recipe that I’ve been giving people. Have...

Extended Pivotal Tracker maintenance on Sat, Oct 2 at 12:00pm PDT
Extended Pivotal Tracker maintenance on Sat, Oct 2 at 12:00pm PDT

Tracker will be unavailable for approximately 3 hours this Saturday, Oct 2, starting at 12:00pm (noon) PDT....

SpringOne. Catch all the highlights

Watch now