How To Vendor Rails
Today I was bitten by the incompatibility of Rack 1.0.0, Passenger 2.2.1, and Rails 22.214.171.124:
undefined method `new' for "Rack::Lock":String (NoMethodError)
Since I had already (inadvertently) upgraded Rack, the solution was to upgrade both Passenger and Rails.
Upgrading Passenger to 2.2.2 was straightforward. Just remember to update the paths in your
passenger.conf to point to the 2.2.2 version.
Upgrading Rails wasn’t quite as straightforward because the compatibility fixes aren’t yet available in the Rails gem. Instead we have to run our application against the latest stable branch, 2-3-stable.
To do this I vendored Rails as a Git submodule. This is nothing new but it’s the first time I’ve needed to do it.
$ git submodule add git://github.com/rails/rails.git vendor/rails $ git commit -m "Vendored Rails edge as a submodule."
This got me running on edge Rails. To run on the 2-3-stable branch I then did:
$ cd vendor/rails/ $ git checkout origin/2-3-stable $ cd ../.. $ git add vendor/rails $ git commit -m "Pinned Rails to branch 2-3-stable as of 4b68deb."
Locally this all worked fine but on deployment the
vendor/rails directory wasn’t populated due to the way submodules work. You have to initialise and update them each time; happily Capistrano supports this with:
set :gitenablesubmodules, true
At this stage it’s a good idea to use a remote cache:
set :deployvia, :remotecache
As and when I go back to running Rails from gems, I’ll remove references to the submodule in
.git/config, and then do:
$ git rm --cached vendor/rails
Finally my application ran again and I could return to working on it rather than the infrastructure…