Bundler

= What is Bundler? =

From the Bundler readme:

"Bundler is a tool that manages gem dependencies for your ruby application. It takes a gem manifest file and is able to fetch, download, and install the gems and all child dependencies specified in this manifest. It can manage any update to the gem manifest file and update the bundle's gems accordingly. It also lets you run any ruby code in context of the bundle's gem environment."

This is the defacto standard for managing gem dependencies with Rails applications as of Rails 3.0, though it can be setup to work with Rails 2.3.5. Prior versions of Rails should freeze their gems instead.

= Getting Started =

There are a few things you need to do in order to use Bundler effectively.

Install Bundler Locally
Install Bundler 0.9.9 (see Compatibility Notes for why you want this version) on your local machine:

gem install bundler -v 0.9.9

Make sure 0.9.9 is the only version installed with:

gem list bundler

If newer versions are installed, you can remove them like so:

gem uninstall bundler -v 0.9.10

If you're on a Mac, you might need to preface the above commands with "sudo".

Rails 2.3.5 Compatibility
This step is only necessary if you're using Rails 2.3.5. Move on to the next step if you're using Rails 3.0 or higher.

You have to take a few special steps to get Bundler working properly with Rails 2.3.5 as mentioned in the Bundler readme and described here. The skinny is you need to make the following changes in your Rails application.

Edit your config/boot.rb file to add the following just above the Rails.boot! line at the end:

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 :default, Rails.env old_load.bind(self).call end end end end

Then add a config/preinitializer.rb file if you don't already have one with the following in it:

begin # Require the preresolved locked set of gems. require File.expand_path('../../.bundle/environment', __FILE__) rescue LoadError # Fallback on doing the resolve at runtime. require "rubygems" require "bundler" if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5") raise RuntimeError, "Bundler incompatible.\n" + "Your bundler version is incompatible with Rails 2.3 and an unlocked bundle.\n" + "Run `gem install bundler` to upgrade or `bundle lock` to lock." else Bundler.setup end end

Get Your App Using Bundler
Now, navigate to your app's root directory and run:

bundle init

That will create a file named Gemfile in that root directory. Next, you want to edit that file, specifying your gem dependencies. You'll put all of those dependencies here rather than in your environment.rb file. You'll want to include at least Rails. You may also want to include Rack (in some cases it matters, in others it doesn't). A sample Gemfile may look like this:

source :gemcutter gem "rails", "~> 2.3.5", :require => nil gem "sqlite3-ruby", :require => "sqlite3" gem "rack", "1.0.1" gem "will_paginate", "2.3.12"

You can specify gems without a version number if you want the latest version.

Packaging Your Gems
Now you want to run the following command on your application:

bundle package

What this command does is pull in copies of the .gem files for all your dependencies and saves them in the vendor/cache directory. It then locks your application to the current versions of gems your application is using at that time, which will generate a Gemfile.lock file.

Note that this step is essential in DreamHost's system as it will perform all the necessary gem dependency resolution on your local machine. That process uses a fair bit of memory and will cause Bundler to get killed for using too much memory on DreamHost servers. By doing this on your local system, it allows Bundler to skip that step when performing the install.

Adding Bundler Files to your Repo
If you're using SVN or Git (or something other SCM) for version control, you'll want to set it up to ignore the .bundle directory inside your application's root directory before checking in. That directory is created when you run bundle install and contains environment-specific information that will need to be rebuilt on the server you're deploying to. So, you want to make sure you add these files:


 * Gemfile
 * Gemfile.lock
 * vendor/cache/*

Install Bundler Remotely
At this point, you'll want to log into your DreamHost shell account and make sure you have Bundler 0.9.9 (see Compatibility Notes for why you want this version) installed under your user there:

gem install bundler -v 0.9.9

Once that's done, you're ready to roll. Deploy your application like you would normally.

Post Deploy
Once you've deployed your application, you need to run this command on the server:

bundle install

Then you want to restart your application. Assuming everything else with your application is working properly, your application should start loading properly. This has been tested with Passenger in our system and appears to work fine. There may be some gems that will cause you to run into additional issues, but in general this should work fine.

= Compatibility Notes =

Bundler 0.9.10
This version of Bundler requires RubyGems 1.3.6, which breaks Passenger due to a bug in Passenger's load path that keeps stringio from loading properly. It also stops requiring the YAML gem by default, which has broken a number of gems. As such, DreamHost servers have not yet been updated to RubyGems 1.3.6 as of the time this was written. If you must have RubyGems 1.3.6, you can compile and install it yourself under your user, but for the purposes of using Bundler with Rails, simply using 0.9.9 for the time being should work fine.

Bundler 0.9.9
This version of Bundler was written against RubyGems 1.3.6, but does not explicitly require that version of RubyGems. Fortunately, all of its major functionality appears to work properly. To install an older version of Bundler, you need to use this syntax:

gem install bundler -v 0.9.9

Older Versions
Older versions of Bundler had fairly major bugs and should be avoided if at all possible.