Rails Load Path Resolution Tip
Nothing ground breaking in this post. I write it only because the existing documentation for this behavior is weak or nonexistent.
Have you ever seen the following message while testing your Rails app?
NameError: uninitialized constant ... blah, blah
In Ruby, .rb files have names that correspond to the class or module name that they include. For example, "car_model.rb" would define a module called "CarModel."
To be able to call CarModel functions in a different class (defined in a different .rb file), you must first use Ruby's "require" or "load" keyword. So, to mix the CarModel module into a class, for example, called "Dealership," you would write:
# assumes car_model.rb is in the same dir as dealership.rb
require "car_model"
class Dealership include CarModeldef add_to_lot(car_model)
puts car_model.name
end
end
If you have lots of modules to mix in, you just keep adding require statements as necessary.
In Rails, however, you can avoid having to explicitly use "require" by going to <your_rails_app>/app/config/environment.rb and adding a line to the config.load_paths as follows:
config.load_paths += %W(
#{RAILS_ROOT}/vendor/net-ssh/lib
#{RAILS_ROOT}/vendor/needle/lib
#{RAILS_ROOT}/vendor/xml-simple/lib
#{RAILS_ROOT}/vendor/flexmock/lib
#{RAILS_ROOT}/app/my_new_load_path/lib
)
Then you can just include and use CarModel without adding a "require" line to dealership.rb.
But even the newest of Ruby/Rails programmers know this much. This isn't what I stopped my progress to write about.
What's noteworthy is that Rails' (at least, in 1.1.6) load path resolution depends on adherence to the convention that your .rb files are lowercased and "_" separated class names. So, if you rename your .rb file and keep the original class name, Rails is suddenly be unable to find your class. If we renamed car_model.rb to car.rb, for asthetic reasons, even though it is included via an entry in environment.rb, the result would be a dependency error like the following:
NameError: uninitialized constant CarModel
method const_missing in dependencies.rb at line 123
method const_missing in dependencies.rb at line 131
method const_missing in dependencies.rb at line 133
To fix the error in this example, either add the require line back into dealership.rb (require "car") or rename your module to "Car" and then fix all the references to it.
my gems plugin will set the vendor load paths automatically: http://svn.techno-weenie.net/projects/plugins/gems/init.rb. It comes w/ a task for unpacking gems to the vendor directory, but also adds vendor/*/lib to the load path for you.
Also, do you really need xml-simple? I think it's used in rails somewhere, so it should be available.
Posted by: rick | November 09, 2006 at 01:45 PM
Rick, thanks for the comment. I just copied my existing config.load_paths into the example. This wasn't to imply that you need to incude stuff like xml-simple to use include.
Posted by: Benjamin Booth | November 18, 2006 at 02:58 AM