Getting started with Bundler

Not too long ago, I learned about bundler. It’s a solution that allows you to have multiple versions of ruby gems installed, specific to the project you’re working on, without affecting the globally installed ruby gems. I’m far from an expert but I hope I can help explain it a bit. To get started, install the bundler gem – it’s the one and only global gem we’ll need to install. You’ll see the dependencies installed as well if you do not have them:

[root@build02 ~]# gem install bundler
Fetching: bundler-1.10.6.gem (100%)
Successfully installed bundler-1.10.6
Installing ri documentation for bundler-1.10.6
1 gem installed

Now, clone a ruby project with a Gemfile. I’ve chosen puppet-retrospec:

[rnelson0@build02 git]$ git clone git@github.com:nwops/puppet-retrospec.git
Initialized empty Git repository in /home/rnelson0/git/puppet-retrospec/.git/
remote: Counting objects: 3246, done.
remote: Compressing objects: 100% (100/100), done.
remote: Total 3246 (delta 45), reused 0 (delta 0), pack-reused 3127
Receiving objects: 100% (3246/3246), 2.32 MiB | 2.67 MiB/s, done.
Resolving deltas: 100% (829/829), done.
[rnelson0@build02 git]$ cd puppet-retrospec/
[rnelson0@build02 puppet-retrospec:master]$

Try and run rake and you’ll notice it’s missing a dependency:

[rnelson0@build02 puppet-retrospec:master]$ rake -T
Could not find addressable-2.3.8 in any of the sources
Run `bundle install` to install missing gems

You can run bundle install on its own, but I prefer to give it a path for the install and to generally avoid system_tests groups. This can be pretty quick for some projects, or take a really long time for anything that includes #&!*# nokogiri (seriously, you’ll learn to hate that one):

[rnelson0@build02 puppet-retrospec:master]$ bundle install --path vendor --without system_tests
Fetching gem metadata from http://rubygems.org/..........
Fetching version metadata from http://rubygems.org/...
Fetching dependency metadata from http://rubygems.org/..
Resolving dependencies...
Installing rake 10.4.2
Installing CFPropertyList 2.2.8
Installing addressable 2.3.8
Installing awesome_print 1.6.1
Installing builder 3.2.2
Using bundler 1.10.6
Installing coderay 1.1.0
Installing thread_safe 0.3.5
Installing descendants_tracker 0.0.4
Installing diff-lcs 1.2.5
Installing facter 2.4.4
Installing fakefs 0.6.7
Installing multipart-post 2.0.0
Installing faraday 0.9.2
Installing git 1.2.9.1
Installing hashie 3.4.2
Installing multi_json 1.11.2
Installing mini_portile 0.6.2
Installing nokogiri 1.6.6.2 with native extensions
Installing jwt 1.5.1
Installing multi_xml 0.5.5
Installing rack 1.6.4
Installing oauth2 1.0.0
Installing github_api 0.12.4
Installing json_pure 1.8.2
Installing hiera 1.3.4
Installing highline 1.7.8
Installing json 1.8.3 with native extensions
Installing rdoc 3.12.2
Installing jeweler 2.0.1
Installing method_source 0.8.2
Installing slop 3.6.0
Installing pry 0.10.2
Using puppet 3.7.3 from source at vendor/gems/puppet-3.7.3
Installing trollop 2.1.2
Installing retrospec 0.4.0
Installing rspec-support 3.3.0
Installing rspec-core 3.3.2
Installing rspec-expectations 3.3.1
Installing rspec-mocks 3.3.2
Installing rspec 3.3.0
Installing yard 0.8.7.6
Bundle complete! 11 Gemfile dependencies, 42 gems now installed.
Gems in the group system_tests were not installed.
Bundled gems are installed into ./vendor.
Post-install message from rdoc:
Depending on your version of ruby, you may need to install ruby rdoc/ri data:

<= 1.8.6 : unsupported
 = 1.8.7 : gem install rdoc-data; rdoc-data --install
 = 1.9.1 : gem install rdoc-data; rdoc-data --install
>= 1.9.2 : nothing to do! Yay!

All of the files were installed to vendor/. There are also files created in .bundle/ and a Gemfile.lock file that tracks the bundler installed gem version-. You’ll most likely want to add those two directories to your .gitignore or you’ll see this all the time:

[rnelson0@build02 puppet-retrospec:master±]$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       vendor/ruby/
nothing added to commit but untracked files present (use "git add" to track)

Now that the gems are installed, you can see and make use of them with bundle exec <command>. Let’s compare the system gems to the bundler gems:

[rnelson0@build02 puppet-retrospec:master±]$ gem list | wc
     78     159    1492
[rnelson0@build02 puppet-retrospec:master±]$ bundle exec gem list | wc
     41      82     712

Finally, let’s take a quick look at how bundler knows what to install. I mentioned a Gemfile.lock tracking file earlier, and it’s based on Gemfile. Here’s what the retrospec project’s looks like:

[rnelson0@build02 puppet-retrospec:master±]$ cat Gemfile
source "http://rubygems.org"

gem 'trollop'
gem 'retrospec', "~> 0.4"
gem 'awesome_print'
# Include everything needed to run rake, tests, features, etc.
group :development do
  gem "rspec", "~> 3.2"
  gem 'puppet', '3.7.3',  :path => 'vendor/gems/puppet-3.7.3'
  gem "yard", "~> 0.7"
  gem "rdoc", "~> 3.12"
  gem "bundler", "~> 1.0"
  gem "jeweler"
  gem 'pry'
  gem "fakefs", :require => "fakefs/safe"
end

Gems by themselves (trollop) will install the latest version. Gems with a version will install a version matching the pattern. ‘1.0’, ‘>=1.3’ probably look familiar, but what does that ‘~> 0.4’ do? It means “Greater than 0.4 but less than 1.0.” If it specifies major.minor.revision, like ‘~> 1.3.2’, it means “Greater than 1.3.2 but less than 1.4.” The path option means to use a gem expanded in the specified location on disk. The require I still don’t understand. From the docs, “If a gem’s main file is different than the gem name, specify how to require it. Specify :require => false to prevent bundler from requiring the gem, but still install it and maintain dependencies.” I guess I’ll find out when I need to know.

I hope this brief intro is helpful to others new to bundler!

4 thoughts on “Getting started with Bundler

  1. Pingback: Adding a gem to your project with bundler | rnelson0
  2. Pingback: Update your Puppet modules on the Forge quickly with Blacksmith | rnelson0
  3. Pingback: Getting a fresh start in a Git repository | rnelson0
  4. Pingback: Modern rspec-puppet practices | rnelson0

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s