Installing a patched RubyGems on TextDrive
Tying up the loose end called "Installing a patched RubyGems on TextDrive your shared host". Sorry this took me so long to write up it should have been posted on August 13th. Anyway the full and gory details follow.
Let's get the tarball for RubyGems 0.9.0 and explode it in the home directory on our shared host:
After making this change it is time to install, since we are installing as non-root we have to make a couple of changes to the standard procedure. Let's go ahead and plan on installing to a directory in the home directory named "myrubygems". Also we will need to specify a GEM_HOME for our local repository (using "/gems" where <HOME> is the full path to your home folder) and we will specify the GEM_PATH to point to the shared hosts gem repository. To find where your shared host keeps its gem repository run the command
Two files left to edit, ~/myrubygems/bin/gem and the RAILS_ROOT/public/dispatch.fcgi. RAILS_ROOT is the path to the rails app you want to pick up the patched RubyGems. Both need the shebang line at the top changed to:
curl -o rubygems-0.9.0.tgz http://rubyforge.rubyuser.de/rubygems/rubygems-0.9.0.tgz
tar xzvf rubygems-0.9.0.tgz
cd rubygems-0.9.0
The tgz distribution can also be found at RubyForge if you don't have curl. Now we need to patch the file ~/rubygems-0.9.0/lib/rubygems/custom_require.rb inside of the RubyGems distribution to make Gem::GemPathSearcher a Singleton. This is chronicled both on this blog and in the still unloved RubyGems patch 5394, reproduced here for ease of cut and paste, minus all comment lines:
require 'rubygems/source_index'
require 'singleton'
module Kernel
alias gem_original_require require
def require(path)
gem_original_require path
rescue LoadError => load_error
begin
@gempath_searcher = Gem::GemPathSearcher.instance
if spec = @gempath_searcher.find(path)
Gem.activate(spec.name, false, "= #{spec.version}")
gem_original_require path
else
raise load_error
end
end
end
end
module Gem
class GemPathSearcher
include Singleton
...
After making this change it is time to install, since we are installing as non-root we have to make a couple of changes to the standard procedure. Let's go ahead and plan on installing to a directory in the home directory named "myrubygems". Also we will need to specify a GEM_HOME for our local repository (using "
gem environment. TextDrive has it installed in the same place as Ruby which will create a little wrinkle for us later.
export GEM_HOME=<HOME>/gems
export GEM_PATH=/usr/local/lib/ruby/gems/1.8/
ruby setup.rb config --prefix=<HOME>/myrubygems
ruby setup.rb setup
ruby setup.rb install
You'll need to modify your $PATH variable to include the patched version of RubyGems first in the list. Here is the line from my .bash_profile file:
export PATH=$HOME/myrubygems/bin:$PATH
Make sure you add this to your $PATH permanently or when your app restarts it will not use the patched version. At this point we can see how we are doing by typing the command which gem it should list the path to the patched version of RubyGems. If not recheck the previous steps.
Two files left to edit, ~/myrubygems/bin/gem and the RAILS_ROOT/public/dispatch.fcgi. RAILS_ROOT is the path to the rails app you want to pick up the patched RubyGems. Both need the shebang line at the top changed to:
#!/usr/local/bin/ruby -I<HOME>/myrubygems/lib/ruby/site_ruby/1.8/
#Again <HOME> needs to be the fully expanded version here for this to work
This is the wrinkle I mentioned earlier. The shebang change is necessary due to the shared host gem repository being installed in the same place as Ruby. The -I option specifies that our patched version of RubyGems be included in the $LOAD_PATH before even Ruby is loaded. I will have more to say about $LOAD_PATH in an upcoming post.