vendor/rails in the Age of Bundler

I’ve only followed the development of Rails 3.0 from a distance, mainly taking note of the major features and goals for the project and mostly ignoring all the little details that go into it. Once the 3.0 release candidate arrived, I started my next internal project with it and have been slowly coming up to speed on those little details. One that’s stymied me for a while is Bundler.

I’ve been using vendor/rails and vendor/gems for a while to fix my dependencies to known versions of third-party code. It was easy to do, and the two main drawbacks didn’t bother me much:

  1. Duplication of code in my project’s repository, making it bigger
  2. Gems with native extensions don’t work (at least, I never bothered trying to make them work)

There is one huge advantage to duplicating this code, though: when the day comes that you hit a bug, you can modify the files in your project, commit them, and move on. With Bundler, it is not obvious how to accomplish this.

Thankfully, what had been missing for me when trying to understand day-to-day use of Bundler now exists: a rationale for why Bundler works the way it does and how to use it as intended. This answered almost all of my questions about how to use Bundler, and led me to a solution for the last one (how to make a local fix).

To make a local fix (for example, in Rails), what I’m now doing is pointing my Gemfile at a fork of the official repository:

gem 'rails', :git => 'http://git.lightyearsoftware.com/rails.git', :tag => '3.0-lys'

This repository contains a branch, 3.0-lys, in which I make my local modifications. It also contains a remote, “upstream”, which tracks the official Rails repository:

$ git remote add upstream git://github.com/rails/rails.git

3.0-lys was branched from v3.0.0, the tag for the official 3.0 release. Note that I didn’t branch it from upstream/3-0-stable because there are changes on this branch that will eventually be part of 3.0.1. When a new release is made of 3.0.x, I’ll merge from the tag into 3.0-lys, keeping it current. Bundler is smart about this, appending a tag to the version number of the “gem” it installs:

$ bundle show
...
  * rails (3.0.0 8b5ee93)
...

Bundler shows a lot of promise, and I’m happy to see the one area that was lacking (documentation) rapidly improving.