Managing Gem dependencies with Rails >= 2.0.3
This is how I manage gem dependencies for Rails applications that use Rails >= 2.0.3.
Specify the dependencies in config.rb.
Rails::Initializer.run do |config|
# ...
config.gem 'doodle'
config.gem 'aws-s3', :lib => 'aws/s3'
config.gem 'smqueue', :version => '0.1.0'
# ...
end
Since I don't want to make my deployment depend on all the gem sources being available I tend to pull the gems into the source tree and check them in.
sudo rake gems:install
rake gems:unpack
svn add vendor/gems/*
When it's time to deploy the application remember to build the gems that have native extensions.
rake gems:build
If you've got some sort of build system in place that produces application packages then this should be done as part of building that package. If you're using Capistrano then it should be done in an after deploy:update_code callback.
Leave feedback...
Commenting is closed for this article.

Note that unless you’re doing this on Rails 2.2 or higher, things may not work well, as the gem stuff was broken in 2.0 and 2.1.
Also note that on 2.2 and above, you should use
rake gems:unpack, as it correctly creates the specification files thatrake gems:buildneeds.Thanks Matt. I hadn’t actually tried this on any release below Rails 2.1.1, I just looked through the Rails commit log for when the feature was added.
Say, should that be “verison => ’0.1.0’”?
Thanks for pointing that out – I’ve fixed it in the article now. Cheers Phillip.
Is it bad practice to have different gem dependencies based on the environment?
I’ve been putting my dependencies in the environment-specific config files since I don’t need mysql support in development (for example).
John: it depends on your setup and how confident you need to be that what works in one environment works on others.
I use SQLite3 on my laptop, but we deploy to a test environment which uses the same setup/code/gems/etc as production (ie it uses MySQL), then to a staging environment which (in theory) is identical to production down to the hardware used.
I suppose you could specify them in each environment, but that’s not very DRY.
Something to consider for future projects!
A very useful summary. I was playing with this a few weeks ago, and it makes some things so much easier and more stable – i.e. you always have the correct versions of gems on all of your environments.
I also like adding plugins as git submodules in /vendor though, especially if they’re my own plugins I’ve extracted from an app but want to make available publicly, or plugins that I need to freeze to a specific (modified) version for some reason. I wonder if they’ll be some convergence of these two approaches in the future.
@Chris – there is some interest in that direction; see ticket 553 for more details.