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...

  1. 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 that rake gems:build needs.

  2. 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.

  3. Say, should that be “verison => ’0.1.0’”?

  4. Thanks for pointing that out – I’ve fixed it in the article now. Cheers Phillip.

  5. 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).

  6. 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.

  7. I suppose you could specify them in each environment, but that’s not very DRY.

    Something to consider for future projects!

  8. 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.

  9. @Chris – there is some interest in that direction; see ticket 553 for more details.

Commenting is closed for this article.

About the boy

A picture of Craig in grayscale

Craig Webster is a software engineer living in London. He usually works with Ruby although sometimes he sneaks in some Erlang or JavaScript. He's into rock climbing, snowboarding, skating, photography and fencing. Yes, this does mean he has a sword.

Near here you'll find Craig's homepage, contact details, PGP key and keysigning policy, and talks.

Licence

The entire content of this blog is public domain. Use it however you fancy. You don't even need to attribute it to me, although it would be nice if you did. Just don't sue me and we'll all be happy.

I Work With Rails

Recommend Me

My Travels

I go places. Do you go places too? Let's meet up!.