Rails 2.3 and Bundler
Here at OtherInbox, we’ve had some issues dealing with gem dependencies using config.gem. Luckily, Carl Lerche and Yehuda Katz have made Bundler for us. Bundler has great dependency resolution and just works™. They’re also smoothing out deployment workflow issues.
Getting Setup with Rails 2.3.x
Setting up Bundler on Rails 2.3.x is fairly straightforward. There’s only 3 steps.
1. setup the Gemfile
2. setup the preinitializer.rb
3. monkey patch the boot.rb
Setup the Gemfile
The Gemfile is the manifest file that lists what gems are part of the application and what environment they belong in. Bundler defaults the gems in vendor/gems/ and the binaries in bin/. Unfortunately, vendor/gems/ is special to rails, so you need to specify a different directoy to use: bundle_path "vendor/bundler_gems". Specifying a gem is as easy as this:
gem "<gem name>", <options>
The options are well, optional. You can specify the version number. You can also specify what to require if the lib doesn’t match gem name. You will need to do this for gems from github, since they’re prefixed with github usernames. There’s also a :only and :except options for specifying which environments the gem should be in. See the following example:
gem 'mislav-will_paginate', '2.3.8', :require_as => 'will_paginate', :except => :test
You can use source to specify different gem sources outside of rubyforge and gemcutter . For instance, I have
source "http://gems.github.com"
in my Gemfile to use github.
You use only and except blocks to specify multiple gems for a particular staging environment.
Here’s my example Gemfile for herocutter:
bundle_path "vendor/bundler_gems"
gem 'rails', '2.3.5'
gem 'postgres'
gem 'clearance', '0.8.4'
gem 'gravtastic', '2.2.0'
gem 'formtastic', '0.9.7'
gem 'git', '1.2.5'
gem 'pacecar', '1.2.0'
only :test do
gem 'factory_girl', '1.2.3'
gem 'cucumber', '0.6.1'
gem 'cucumber-rails', '0.2.3'
gem 'webrat', '0.6.0'
gem 'database_cleaner', '0.4.2'
gem 'shoulda', '2.10.2'
gem 'rr', '0.10.5'
gem 'redgreen'
end
only :development do
gem 'factory_girl', '1.2.3'
gem 'n', '0.1.0'
end
Don’t forget to remove the gems from the vendor/gems/ directory and the config.gem lines from your environment files.
Caveat
If you use disable_system_gems to not search your system gems, it will not work on heroku since their system is dependent on a system install version of thin.
In a consulting project when I’ve made the switch to bundler, all monkey patched gems I’ve kept those inside vendor/gems/ as well as the appropriate config.gem lines in the environment files. If you need to require their dependencies in bundler, rails won’t load the depencies properly when accessed in the lib/ directory. For instance, in a monkey patch to lockdown I used ParseTree and had to require that explicitly in lib/lockdown/init.rb.
Setup the preinitializer.rb
This step is simple. In your config/preinitializer.rb, you need to get rails to load bundler in the path by adding:
require "#{File.dirname(__FILE__)}/../vendor/bundler_gems/environment"
Caveat
In Yehuda’s blog post, insert the environment loading code into the config/preinitializer.rb. I couldn’t get it to work quite right.
Monkey Patch the boot.rb
Instead of putting loading of the environment gems in config/preinitializer.rb, I found it works better to monkey patch config/boot.rb directly (got this from the gemcutter source). We basically need to tell rails to load the right environment gems. You can do this by adding this to the bottom of config/boot.rb right before the Rails.boot!:
class Rails::Boot
def run
load_initializer
extend_environment
Rails::Initializer.run(:set_load_path)
end
def extend_environment
Rails::Initializer.class_eval do
old_load = instance_method(:load_environment)
define_method(:load_environment) do
Bundler.require_env RAILS_ENV
old_load.bind(self).call
end
end
end
end
You can also refer to the config/boot.rb on herocutter to see what I changed exactly.
Version Control
You can ignore the vendor/bundler_gems/ directory since it gets created when running the gem bundle command.
archive
- Rails 2.3 and Bundler - 02 Feb 2010
- Guide to Heroku Plugins - 09 Jan 2010
links :
- feed
- code @ github
- rack-jekyll powered
- licensed with creative commons
- hosted by heroku