simple web Engineering
December 19 2009
random Rails tips Vol. 2
My series of random Rails tips that started a month ago continues with some tips on how to use wycats’ bundler gem. What bundler does is basically maintaining and resolving a project’s gem dependencies (and the dependencies of these gems) and bundling all required gems in vendor/gems. This is what Rails’ gems:x tasks where intended to do, but never really did sufficiently. Where the rake tasks would frequently fail since the environment that the tasks themselves needed to execute could not be set up because it depended on the gems the tasks where intended to install, bundler is completely independent (only rubygems and the bundler gem itself are needed of course).
Setting it up
To set up bundler for your project, you first need to create a Gemfile in that you specify all dependencies your application has. You can specify versions, the libs to include (if they could not be resolved from the gem name) and also require certain gems only in certain environments. A sample gem file for a Rails app using DataMapper (expect more on using DataMapper with Rails in a future post of my random Rails tips series) might look like this:
In the first line, the path is specified where bundler holds the *.gem files, the extracted gem sources etc. The second line disables the system’s gems so that any gems that might be installed on your machine but are not bundled with the application will not be loaded. This is pretty important to be sure that the application is actually self contained and you didn’t forget to specify a dependency which didn’t lead to errors because the missing gem was installed on your machine.
The last block in the gem file specifies gems that are needed everywhere except for the production environment. While you need gems like rspec, rspec-rails or excellent in the test and possibly also in the development environment, you certainly don’t need these gems to be installed on your production machine(s).
Using bundler
Of course you need to make sure that the bundled gems will actually be used (Rails 3 will support bundler out of the box, however Rails 2.3 doesn’t; see qrush’s commit to the gemcutter.org source). Therefore you have to add a preinitializer.rb in your app’s config directory:
Yehuda describes a different solution in his blog post but that doesn’t work with Passenger under certain conditions. You also have to edit your boot.rb to include the following block right at the end:
When everything is set up, you can run gem bundle from your app’s root and bundler will install all the required gems:
You now have all gems your app requires bundled in vendor/gems and are ready to run ./script/server/.
Deployment with the bundler gem
Deploying you app with the help of bundler is a breeze. It’s as easy as adding two tasks to your deploy.rb (assuming you’re using Capistrano; thanks jerryvos for pointing that out):
This will keep all your app’s gems in shared/vendor/gems and make sure that whenever a new gem is required and not bundled on the server (or a new version is available and you’re not requiring exact versions), it is installed.
Using the bundler gem makes your life a lot easier, works pretty good already and there really is no reason to wait for Rails 3 to use it. So everybody go ahead: gem install bundler!
