A common way to add gems to vendor/gems is by using the gem unpack command.
cd vendor/gems
gem unpack the_gem_name
And then loading them up using an approach like this, this, or something like this:
Dir.glob(File.dirname(__FILE__) + "/../vendor/gems/*").each do |path| gem_name = File.basename(path.gsub(/-[\d\.]+$/, '')) $LOAD_PATH << path + "/lib/" require gem_name end
This feels like it should be unnecessary since Rubygems comes with a method to load a gem (gem). It's really a second class way of using gems.
Here's a solution I've been using for a while to keep gem code in vendor/gems, but still load them using the regular gem method.
First, a rake task to install gems.
namespace :gem do desc "install a gem into vendor/gems" task :install do if ENV["name"].nil? STDERR.puts "Usage: rake gem:install name=the_gem_name"; exit 1 end sh "gem install #{ENV['name']} --install-dir=vendor/gems --no-rdoc --no-ri" end end
Then, a little Rubygems magic to change GEM_PATH (I placed it at the top of environment.rb).
require "rubygems" Gem.clear_paths gem_paths = [ File.expand_path("#{File.dirname(__FILE__)}/../vendor/gems"), Gem.default_dir, ] gem_paths << APPLE_GEM_HOME if defined?(APPLE_GEM_HOME) Gem.send :set_paths, gem_paths.join(":")
Finally, using gems works in typical Rubygems fashion.
# somewhere in the code base gem "hpricot", "0.6" require "hpricot"
I like this gem install approach better than the gem unpack one. Gem dependencies are being added to Rails in 2.1, which should make this unnecessary. When I first looked at the code, it was using gem unpack, but also extracting the gem specification. I'm not sure if setting gem_path like this could simplify the Rails implementation or not.
I only tested this approach on a Rails 2.0.2 app, using Rubygems 0.9.5 and 1.1.1. One additional benefit is that if you want to make sure your app doesn't depend on any locally installed gems, you can make vendor/gems the only directory in the gem path (although CruiseControl should be helping you with that problem anyway).