Sponsors


Blog powered by TypePad

« Google Aquires Jotspot | Main | The Rails Edge, 2006 - Day 1 »

November 09, 2006

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 CarModel

    def 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.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/t/trackback/277049/6774192

Listed below are links to weblogs that reference Rails Load Path Resolution Tip:

Comments

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.

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.

Post a comment

If you have a TypeKey or TypePad account, please Sign In