11.2. Bundler

In a Rails project, different gems are used (see Section 11.1, “Gems”) and a developer can also add further gems. Bundler helps the developer to install all these gems in the right version and to take into account important dependencies. In previous Rails versions, you as developer had to always call a bundle install after a rails new. Now, this is done automatically within rails new. In the output you can see which gems are installed by bundle install:
$ rails new webshop
  [...]
         run  bundle install
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/..
Using rake (10.0.2) 
Using i18n (0.6.1) 
Using multi_json (1.3.7) 
Using activesupport (3.2.9) 
Using builder (3.0.4) 
Using activemodel (3.2.9) 
Using erubis (2.7.0) 
Using journey (1.0.4) 
Using rack (1.4.1) 
Using rack-cache (1.2) 
Using rack-test (0.6.2) 
Using hike (1.2.1) 
Using tilt (1.3.3) 
Using sprockets (2.2.1) 
Using actionpack (3.2.9) 
Using mime-types (1.19) 
Using polyglot (0.3.3) 
Using treetop (1.4.12) 
Using mail (2.4.4) 
Using actionmailer (3.2.9) 
Using arel (3.0.2) 
Using tzinfo (0.3.35) 
Using activerecord (3.2.9) 
Using activeresource (3.2.9) 
Using bundler (1.2.1) 
Using coffee-script-source (1.4.0) 
Using execjs (1.4.0) 
Using coffee-script (2.2.0) 
Using rack-ssl (1.3.2) 
Using json (1.7.5) 
Using rdoc (3.12) 
Using thor (0.16.0) 
Using railties (3.2.9) 
Using coffee-rails (3.2.2) 
Using jquery-rails (2.1.3) 
Using rails (3.2.9) 
Using sass (3.2.3) 
Using sass-rails (3.2.5) 
Using sqlite3 (1.3.6) 
Using uglifier (1.3.0) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
$ cd webshop 
$ 
The file Gemfile generated by rails new indicates which gems are to be installed by Bundler:
source 'https://rubygems.org'

gem 'rails', '3.2.9'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'sqlite3'


# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  # gem 'therubyracer', :platforms => :ruby

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'

# To use Jbuilder templates for JSON
# gem 'jbuilder'

# Use unicorn as the app server
# gem 'unicorn'

# Deploy with Capistrano
# gem 'capistrano'

# To use debugger
# gem 'debugger'
The format used is easy to explain: the word gem is followed by the name of the gem and then, if required, a specification of the version of the gem.
For example, the line gem 'rails', '3.2.9' stands for "install the gem with the name rails in the version 3.2.9".
With ~> before the version number you can determine that the newest version after this version number should be installed. As a result, the last digit is incremented, so for example gem 'rails', '~> 3.2.3' would correspondingly install a Rails 3.2.9, but not a 3.3 (for the latter, you would need to specify gem 'rails', '~> 3.2').

Important

You have the option of installing certain gems only in certain environments. To do so, you need to enclose the corresponding lines in a group :name do loop.
Apart from the file Gemfile there is also the file Gemfile.lock and the exact versions of the installed gems are listed there. In the above example, it looks like this:
GEM
  remote: https://rubygems.org/
  specs:
    actionmailer (3.2.9)
      actionpack (= 3.2.9)
      mail (~> 2.4.4)
    actionpack (3.2.9)
      activemodel (= 3.2.9)
      activesupport (= 3.2.9)
      builder (~> 3.0.0)
      erubis (~> 2.7.0)
      journey (~> 1.0.4)
      rack (~> 1.4.0)
      rack-cache (~> 1.2)
      rack-test (~> 0.6.1)
      sprockets (~> 2.2.1)
    activemodel (3.2.9)
      activesupport (= 3.2.9)
      builder (~> 3.0.0)
    activerecord (3.2.9)
      activemodel (= 3.2.9)
      activesupport (= 3.2.9)
      arel (~> 3.0.2)
      tzinfo (~> 0.3.29)
    activeresource (3.2.9)
      activemodel (= 3.2.9)
      activesupport (= 3.2.9)
    activesupport (3.2.9)
      i18n (~> 0.6)
      multi_json (~> 1.0)
    arel (3.0.2)
    builder (3.0.4)
    coffee-rails (3.2.2)
      coffee-script (>= 2.2.0)
      railties (~> 3.2.0)
    coffee-script (2.2.0)
      coffee-script-source
      execjs
    coffee-script-source (1.4.0)
    erubis (2.7.0)
    execjs (1.4.0)
      multi_json (~> 1.0)
    hike (1.2.1)
    i18n (0.6.1)
    journey (1.0.4)
    jquery-rails (2.1.3)
      railties (>= 3.1.0, < 5.0)
      thor (~> 0.14)
    json (1.7.5)
    mail (2.4.4)
      i18n (>= 0.4.0)
      mime-types (~> 1.16)
      treetop (~> 1.4.8)
    mime-types (1.19)
    multi_json (1.3.7)
    polyglot (0.3.3)
    rack (1.4.1)
    rack-cache (1.2)
      rack (>= 0.4)
    rack-ssl (1.3.2)
      rack
    rack-test (0.6.2)
      rack (>= 1.0)
    rails (3.2.9)
      actionmailer (= 3.2.9)
      actionpack (= 3.2.9)
      activerecord (= 3.2.9)
      activeresource (= 3.2.9)
      activesupport (= 3.2.9)
      bundler (~> 1.0)
      railties (= 3.2.9)
    railties (3.2.9)
      actionpack (= 3.2.9)
      activesupport (= 3.2.9)
      rack-ssl (~> 1.3.2)
      rake (>= 0.8.7)
      rdoc (~> 3.4)
      thor (>= 0.14.6, < 2.0)
    rake (10.0.2)
    rdoc (3.12)
      json (~> 1.4)
    sass (3.2.3)
    sass-rails (3.2.5)
      railties (~> 3.2.0)
      sass (>= 3.1.10)
      tilt (~> 1.3)
    sprockets (2.2.1)
      hike (~> 1.2)
      multi_json (~> 1.0)
      rack (~> 1.0)
      tilt (~> 1.1, != 1.3.0)
    sqlite3 (1.3.6)
    thor (0.16.0)
    tilt (1.3.3)
    treetop (1.4.12)
      polyglot
      polyglot (>= 0.3.1)
    tzinfo (0.3.35)
    uglifier (1.3.0)
      execjs (>= 0.3.0)
      multi_json (~> 1.0, >= 1.0.2)

PLATFORMS
  ruby

DEPENDENCIES
  coffee-rails (~> 3.2.1)
  jquery-rails
  rails (= 3.2.9)
  sass-rails (~> 3.2.3)
  sqlite3
  uglifier (>= 1.0.3)
The advantage of Gemfile.lock is that it makes it possible for several developers to work on the same Rails project independently from one another and to still be sure that they are all working with the same gem versions. If a file is Gemfile.lock, this will be used by the Bundler. This is also useful for deploying the Rails project later on a web server.
Thanks to this mechanism you can use and develop several Rails projects with different gem version numbers in parallel.

bundle update

With bundle update you can update gems to new versions. As an example, I have a Rails project with the Rails version 3.2.5:
$ rails -v
Rails 3.2.5
$
In the file Gemfile, this version is listed:
$ head -n 4 Gemfile
source 'https://rubygems.org'

gem 'rails', '3.2.5'

$ 
And also in the Gemfile.lock:
$ grep 'rails' Gemfile.lock 
    coffee-rails (3.2.2)
    jquery-rails (2.0.2)
    rails (3.2.5)
    sass-rails (3.2.5)
  coffee-rails (~> 3.2.1)
  jquery-rails
  rails (= 3.2.5)
  sass-rails (~> 3.2.3)
$
If we want to update this Rails project to the Rails version 3.2.6, we need to change the entry in the Gemfile as follows:
source 'https://rubygems.org'

gem 'rails', '3.2.6'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'sqlite3'


# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  # gem 'therubyracer', :platforms => :ruby

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
After this change, you can use bundle update rails to install the new Rails version (required dependencies are automatically taken into account by Bundler):
$ bundle update rails
Fetching gem metadata from https://rubygems.org/.........
Using rake (0.9.2.2) 
Using i18n (0.6.0) 
Using multi_json (1.3.6) 
Installing activesupport (3.2.6) 
Using builder (3.0.0) 
Installing activemodel (3.2.6) 
Using erubis (2.7.0) 
Using journey (1.0.4) 
Using rack (1.4.1) 
Using rack-cache (1.2) 
Using rack-test (0.6.1) 
Using hike (1.2.1) 
Using tilt (1.3.3) 
Using sprockets (2.1.3) 
Installing actionpack (3.2.6) 
Using mime-types (1.19) 
Using polyglot (0.3.3) 
Using treetop (1.4.10) 
Using mail (2.4.4) 
Installing actionmailer (3.2.6) 
Using arel (3.0.2) 
Using tzinfo (0.3.33) 
Installing activerecord (3.2.6) 
Installing activeresource (3.2.6) 
Using bundler (1.1.4) 
Using coffee-script-source (1.3.3) 
Using execjs (1.4.0) 
Using coffee-script (2.2.0) 
Using rack-ssl (1.3.2) 
Using json (1.7.3) 
Using rdoc (3.12) 
Using thor (0.15.4) 
Installing railties (3.2.6) 
Using coffee-rails (3.2.2) 
Using jquery-rails (2.0.2) 
Installing rails (3.2.6) 
Using sass (3.1.20) 
Using sass-rails (3.2.5) 
Using sqlite3 (1.3.6) 
Using uglifier (1.2.6) 
Your bundle is updated! Use `bundle show [gemname]` to see where a bundled gem is installed.
$ rails -v
Rails 3.2.6
$

Important

After every gem update, you should first run your tests to make sure that a new gem version does not add any unwanted side effects.

bundle outdated

If you want to know which of the gems used by your Rails project are now available in a new version, you can do this via the command bundle outdated. Example:
$ bundle outdated
Fetching gem metadata from https://rubygems.org/.........

Outdated gems included in the bundle:
  * sprockets (2.4.4 > 2.1.3)

$

bundle exec

bundle exec is probably one of the commands Rails developers hate the most. It is required whenever a program such as rake is used in a Rails project and is present in a different version than the rest of the system. The resulting error message is always easy to implement:
You have already activated rake 0.10, but your Gemfile requires rake 0.9.2.2. Using bundle exec may solve this.
In this case, it helps to invoke the command with a preceding bundle exec:
$ bundle exec rake db:migrate

binstubs

In some environments, using bundle exec is too complicated. In that case, you can install programs with the correct version via bundle install --binstubs in the directory bin:
$ bundle install --binstubs
Using rake (0.9.2.2) 
Using i18n (0.6.0) 
Using multi_json (1.3.6) 
Using activesupport (3.2.6) 
Using builder (3.0.0) 
Using activemodel (3.2.6) 
Using erubis (2.7.0) 
Using journey (1.0.4) 
Using rack (1.4.1) 
Using rack-cache (1.2) 
Using rack-test (0.6.1) 
Using hike (1.2.1) 
Using tilt (1.3.3) 
Using sprockets (2.1.3) 
Using actionpack (3.2.6) 
Using mime-types (1.19) 
Using polyglot (0.3.3) 
Using treetop (1.4.10) 
Using mail (2.4.4) 
Using actionmailer (3.2.6) 
Using arel (3.0.2) 
Using tzinfo (0.3.33) 
Using activerecord (3.2.6) 
Using activeresource (3.2.6) 
Using coffee-script-source (1.3.3) 
Using execjs (1.4.0) 
Using coffee-script (2.2.0) 
Using rack-ssl (1.3.2) 
Using json (1.7.3) 
Using rdoc (3.12) 
Using thor (0.15.4) 
Using railties (3.2.6) 
Using coffee-rails (3.2.2) 
Using jquery-rails (2.0.2) 
Using bundler (1.1.4) 
Using rails (3.2.6) 
Using sass (3.1.20) 
Using sass-rails (3.2.5) 
Using sqlite3 (1.3.6) 
Using uglifier (1.2.6) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
$ ls bin
erubis  rake  ri  scss  tt
rackup  rake2thor sass  thor
rails   rdoc      sass-convert   tilt
$
Afterwards, you can always use these programs. Example:
$ bin/rake db:migrate
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.0018s
==  CreateUsers: migrated (0.0019s) ===========================================

$

Further Information on Bundler

The topic Bundler is far more complex than can be described here. If you want to find out more on Bundler, please visit the following websites to find further information:

Updates about this book will be published on my Twitter feed.