Last modified 8 years ago Last modified on 06/25/10 23:15:46


Using Bundler to manage Gems in a Rails project

It's not uncommon to download and experiment with lots of gems while one is developing a Rails application. The gems usually end up installed either in a system-wide directory (shared by all of the system's users) or in a user's personal directory (typically located under ~/.gem). Often, one isn't ready to settle on a particular gem (or version thereof) during this experimentation phase. This approach to gem storage is simple and convenient, but it can also lead to several problems later on.

To begin with, any upgrades to the system-wide (or personal) gem directories can cause sudden incompatibilities to arise for existing applications. Also, different applications running on the same system may require different versions of the same gem. There are mechanisms available for dictating which version of a library should be loaded by an application (see this page and subsequent chapters of the RubyGems? documentation for details), but versioning is only one facet of gems management.

In instances where an application is to be stored in a source code repository, checked-out by other developers, and deployed to test and production environments on machines other than where the application was first developed, it's advantageous to check-in the gems that an application depends on as part of the project.

There are at least a couple of methods for including gems in a Rails project:

The following article give an overview of the various approaches one can employ:

The purpose of this document is to provide instructions for installing and using Bundler to manage an application's gems. Bundler is similar to the unpack and freeze approach.

Assumptions for this discussion

  • OS version is Mac OS X 10.5.8.
  • Ruby version is 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0].
  • MacPorts? 1.8.1 installed, along with ports: postgresql83 and postgresql83-server.
  • Unless otherwise noted, all steps are carried out as a user with administrative privileges.
  • $RAILS_APP_ROOT is set to the path of your Rails application root directory.

Install Bundler

It's ok to install this for system-wide access.

sudo gem install bundler

Create the manifest file

Bundler's manifest file is named 'Gemfiles' and should be created in the project's root directory. The manifest file contains a list of gems that are required by your application, along with an assortment of other configuration parameters. At a minimum, you must require at least one gem, so start by requiring the 'rails' gem. To determine which version of that gem to require, examine $RAILS_APP_ROOT/config/environment.rb and find a line that looks similar to the following:

RAILS_GEM_VERSION = '2.3.2' unless defined? RAILS_GEM_VERSION

Now, create an initial version of '$RAILS_APP_ROOT/Gemfile' that includes some basic configuration information:

# Specify that rubygems should be completely disabled. This means that it
# will be impossible to require it and that available gems will be
# limited exclusively to gems that have been bundled.

# Specify a dependency on rack v.1.0.0. The version is optional. If present,
# it can be specified the same way as with rubygems' #gem method.
gem "rack", "1.0.0"

# At least one dependency must be specified.  This will trigger the inclusion
# of several other dependencies including:  actionmailer, activeresource,
# actionpack, activesupport, activerecord, and rake.
gem "rails", "2.3.2"

# You will need to install some form of database support.  The project in this example
# has a PostgreSQL back-end.
gem "postgres"
#gem "mysql"
#gem "sqlite3-ruby"

This step will likely need to be repeated several times, meaning: I don't know of an easy way to determine the complete list of gems required by any given project unless those gems and their version numbers are already listed somewhere else. Typically what do is 1.) start with a minimal list like the one above, 2.) run through the remainder of this process until I hit a problem (e.g. exceptions encountered while trying to start the rails application, while using the application, or during a gem's installation if something fails to compile because the gem needs additional flags or environment variables to be set), and 3.) add whatever missing gems I find to Gemfile and repeat the bundling process.

Create a build options file

Build options and architecture type may need to be specified for some libraries to compile and install correctly (e.g. PostgreSQL and MySQL). On my workstation, PostgreSQL was installed using MacPorts?, hence the database's libraries and includes are stored under /opt/local.

Create a file called 'build_options.yml' in the projects root directory, and add the following text:

      pgsql-lib: /opt/local/lib/postgresql83
      pgsql-include: /opt/local/include/postgresql83

For more information installing configuring the postgres gem, please see this article).

Bundle the gems

Run Bundler to download, cache and install all required gems (and dependencies). By default, all gems will be stored under the project's vendor/gems directory.

export ARCHFLAGS='-arch i386'  # required to build the postres gem
gem bundle --build-options build_options.yml

Run the application

It's time to start-up your Rails application and look for missing gems. Make sure to preface the call to Ruby with 'gem exec'.

gem exec ruby script/server

To avoid having to type 'gem exec', place the following line at at top of file config/preinitializer.rb:

require "#{RAILS_ROOT}/vendor/gems/environment"

You may then run your application using the good old:

ruby script/server


Bundler gem at Github
RubyGems manuals