brettu brettu - 4 months ago 16
Ruby Question

Why do Rails /lib modules prevent gem modules from loading?

The title of this question may need renaming. Any suggestions?

In my Rails application there was an old Module in the /lib folder called foo_blaster.rb. I then installed my gem named foo_blaster.rb. None of the code in the gem executed until I deleted the original FooBlaster module. Why is this? Shouldn't Ruby combine the two Modules?

The Modules are the same

# lib/foo_blaster.rb
module FooBlaster
class Characters
puts "some characters"
end
end

# foo_blaster gem files
module FooBlaster
class Users
end
end

FooBlaster::Characters #=> some characters
FooBlaster::Users #=> NameError: uninitialized constant FooBlaster::Users


What am I missing here?

Rails 2.3.18,
Ruby 1.8.7-p358

Answer

If you open up a console (with script/console) and examine the $LOAD_PATH variable, you should see something resembling this:

>> $LOAD_PATH
[
  # some entries...
  [12] "/your/rails/root/app",
  [13] "/your/rails/root/app/controllers",
  [14] "/your/rails/root/app/models",
  [15] "/your/rails/root/app/helpers",
  [16] "/your/rails/root/lib",
  # more entries...
  [27] "/your/ruby/path/lib/ruby/1.8/gems/foo_blaster-0.0.1/lib"
  # rest of entries
]

When you require 'foo_blaster' (which may be done implicitly by Rails, Bundler, or perhaps some other means), Ruby searches the locations in $LOAD_PATH sequentially until it finds the file foo_blaster.rb, loads that file, and stops. In your case, it finds the file in your application's /lib directory. The file from your gem will never be loaded.

If you want to load both files, all you have to do is give them different names and make sure to require them both. For instance, you might rename the file in your application to foo_blaster_extensions.rb, then add an initializer to load it:

# config/initializers/extend_foo_blaster.rb
require 'foo_blaster_extensions'