Gem insanity

I just finished upgrading to rails 3 and went through the various contortions to get my rails applications running. Then for some reason, I decided to try to run a standalone ruby script that uses activerecord to fetch some records from one of my databases. It blows up with:

/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:53:in `gem_original_require': no such file to load -- activerecord (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:53:in `require'

Now, I know two things. One is that this script used to work just fine. Two is that my current rails setup (which includes activerecord) works just fine. So, what is up??

The lines in the script that used to pull in activerecord are:

require "rubygems"
gem "activerecord"
require "activerecord"
I spent a day pulling my hair out, learning things about the gem system, doing many google searches. I won't tell you just yet how I figured this out, but the fix is to replace the 3 lines above with the following two:
require "rubygems"
require "active_record"
For reasons that I haven't the foggiest idea about, the "gem" call is no longer needed. What blows completely over the top is that somewhere along the line, somebody apparently decided to rename activerecord to active_record or something of the sort!

And it turns out is is just that simple. Some moron, with imbecility beyond normal limits, decided to rename the file activerecord.rb to active_record.rb.

/usr/lib/ruby/gems/1.8/gems/activerecord-3.0.9/lib/active_record.rb
Note that the package name (activerecord) differs from the file (active_record.rb)

The gem actionpack suffers from the same malady, to pull it in you do:

require "rubygems"
require "action_pack"

Reporting this as a bug

First I went to rubyforge (as some link directed me) to report this as what became RubyForge Bug 29300. I was then told to make a duplicate submission on github, so I did, reporting this as issue 125. I quickly got two replies, both telling me that the simple truth is that they changed the name of the file from activerecord.rb to active_record.rb, so rubygems has nothing at all to do with this.

What does the "gem" method do?

The word is that the sort of obsolete "gem" command adds a ruby gem to the load path, and loads any required gems. Clearly it didn't put the activerecord gem on the load path in any useful way, or this document wouldn't even exist. Maybe it did this once and now it is broken, who knows. What the gem command might be useful for in the current scheme of things is to specify a version number of a gem prior to a subsequent require, in the following manner:
require "rubygems"
gem "activerecord", "= 0.14.4"
require "activerecord"
The lingo is that the gem command "activates" the gem, prior to loading it.

By default, the files comprising a gem are not in the usual ruby load path. What rubygems does is to extend the standard 'require' command so that if a file is not found, a method in rubygems is called and sets things up so that the files for the gem can be found.

A bunch of gem tricks

In the process of trying to figure this out (and I just got lucky with a google search not quite related to my actual problem), I learned some of the following tricks:

First off, the interactive ruby thing called irb is quite handy for testing this kind of stuff:

irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'action_pack'
=> true
irb(main):003:0> require "actionpack"
LoadError: no such file to load -- actionpack
	from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require'
	from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
	from (irb):4
	from /usr/lib/ruby/site_ruby/1.8/rubygems/dependency_list.rb:8
irb(main):004:0> require 'rails'
=> true
irb(main):005:0> exit

The ruby load path (called $:) can be inspected and meddled with to attempt to fix this problem. I wrongly focused a lot of attention here because I knew that activerecord was on my system, the question was why ruby was not finding it.

The command line command "gem" has many options, including the following:

gem env
gem query
gem list --local (same as gem query)
gem list --remote
gem install pkg
gem uninstall pkg

Inside of ruby, the Gem object has many methods that can yield useful information. Gem.path is one of these things.

You can set environment variables, such as GEM_PATH and others.

A thing called "rvm" is a way to manage multiple ruby versions, set of gems, and a world of chaos that gives me a headache to just ponder.


Feedback? Questions? Drop me a line!

Ruby on Rails notes / tom@mmto.org