Working with Bundler
Writing Ruby code by yourself can be fun, but distributing it (either for use or other developers) can be a huge pain, thanks largely to changes in RubyGems and incompatibility between different gems. The Bundler project makes life so much easier. I use it in projects or even simple tools I write, mostly because I want my code to be used. Bundler has been out for a very long while, but I know a few people who haven’t used it much yet, so I figured there might be more of you out there.
So, here’s how we get started:
First, examine all the gems your project requires. This should be pretty easy to figure out if you’re doing things right:
1 2 3 4 5 6 7 8 9 10 11 |
#!/usr/bin/env ruby require 'rubygems' require 'sinatra' require 'json' require 'dm-core' require 'dm-validations' require 'dm-timestamps' require 'dm-migrations' require 'dm-types' # Ruby Code starts here... |
You can see here that I’m requiring a few gems for the Sinatra lightweight web app framework, the JSON gem, and several DataMapper gems. This works great now, but at some point, the latest version of one gem might become incompatible with the latest version of another (say Sinatra and DataMapper). To ensure we always have all of our gems installed at compatible versions, we can create a Gemfile (simply called Gemfile) and place it in the project’s root:
1 2 3 4 5 6 7 8 9 10 |
source "http://rubygems.org" gem "json", "~>1.7" gem "sinatra", "~>1.3" gem "data_mapper", "~>1.2" gem "dm-sqlite-adapter" platforms :jruby do gem "do_jdbc" gem "jdbc-sqlite3" end |
This file is pretty easy to follow, and just tells Bundler:
- Where to pull gems from (in this case, rubygems.org)
- To use a version of the JSON gem at version 1.7 or greater, up to and including version 1.9
- To use a version of the Sinatra gem at or greater than 1.3, up to and including version 1.9
- To use a version of the DataMapper gem at or greater than 1.2, up to and including version 1.9
- To use the latest version of DataMapper’s sqlite adapter
- On the JRuby platform (meaning when you’re using JRuby) we also:
- Use the DataObject JDBC gem for connecting to databases
- Use the JDBC SQLite3 gem
We needed to limit the JRuby gems, since they wouldn’t work on standard Ruby.
To use the gems installed by Bundler, we need to modify our application slightly to include another gem:
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/env ruby require 'rubygems' require "bundler/setup" require 'sinatra' require 'json' require 'dm-core' require 'dm-validations' require 'dm-timestamps' require 'dm-migrations' require 'dm-types' # Ruby Code starts here... |
Notice the subtle difference there? We added require "bundler/setup" which tells the application it will be requiring gems from the Bundler environment.
Now, the moment of truth. To make sure we have all of our gems at the right version, lets test out “Bundler” on a new machine.
First, let’s install the Bundler gem (this may need to be run as root if you’re using your system Ruby):
$ gem install bundler |
After that, and after we’ve gotten the code to our test environment, open up a terminal and change directory into our project’s root, then type this:
$ bundle install |
You may need to run this command as root or the equivalent using sudo or the like. If we get a message like this:
Your bundle is complete!
Then you’re good. Try running your application at that point:
$ ruby main.rb |
You’ll notice that Bundler created a new file in your project directory called Gemfile.lock. This file is used to list out the exact versions of all gems installed by Bundler, including their dependencies. Again, this is useful to make sure everything is installed at the exact and expected versions. You’ll want this file, along with the Gemfile itself to be kept under version control.

