Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespaced modules and Rails 3.1.3 autoload_path

I'm having some trouble to namespace a module that I include in a model.

in /app/models/car.rb

class Car
 include Search::Car
end

in /lib/search/car.rb

module Search
  module Car
    include ActiveSupport::Concern
    # methods in here
  end
end

in /config/application.rb

config.autoload_paths += Dir["#{config.root}/lib/**/"]
config.autoload_paths += Dir["#{config.root}/lib/search/*"]

The weird thing is that I don't get any errors directly when I fire up the server. But if I refresh the browser after a while I get this error:

Expected #{Rails.root}/lib/search/car.rb to define Car

The nature of the problem indicates that it has something to do with:

/config/environments/development.rb

config.cache_classes = false

I also tried put a file search.rb directly in /lib where I define Search:

module Search
  # Put shared methods here
end

What am I doing wrong?

UPDATE:

Ok, turns out that if I rename Search::Car to Search::CarSearch it works. Is it not possible to have Modules/Classes of the same name in a different scope?

like image 633
Yeggeps Avatar asked Feb 16 '12 22:02

Yeggeps


1 Answers

The error is coming from your autoload_paths. config.autoload_paths += Dir["#{config.root}/lib/**/"] will add all directories and their subdirectories under lib directory. meaning that you are telling rails to autoload lib/search/ directory, therefore car.rb under that directory is expected to define Car and not Search::Car. In order for rails to expect lib/search/car.rb to define Search::Car, you need to autoload lib/ directory and not lib/search. if you change you autoload to config.autoload_paths += Dir["#{config.root}/lib/"] and put search.rb in lib/ with following code:

module Search
  require 'search/car'
end

then rails will understand and expect lib/search/car.rb do define Search::Car and referencing Car module/class in other places of your code will not reference to this car.rb.

You should remove this line (you should only have autoload for lib directory): config.autoload_paths += Dir["#{config.root}/lib/search/*"]

like image 181
Iuri G. Avatar answered Oct 05 '22 01:10

Iuri G.