4

Rails 3.2.6 には 2 つのクラスがあります。

  • models/foo.rb のクラス Foo (デフォルトではテーブル foos にあります)
  • classes/bar/foo.rb の Bar::Foo クラス ( にself.table_name設定bar_foos)

コンソールに入ると、次のようになります。

> Bar::Foo
=> Bar::Foo(id: ...)
> Foo # or ::Foo
LoadError: expected models/bar/foo.rb to define Foo

どうしたの?

4

2 に答える 2

5

We solved this in IRC, but the core issue is that there was a config.autoload_paths glob set that was including models/** as load paths.

Rails' auto-loader iterates the load paths, and tacks on the constant name. Once it finds a file that exists, it tries to load it, then throws an exception if the constant is not available.

So, what was happening is Rails had a list of load paths like:

/models/bar/
/models/

It was iterating the paths, and would find a match at /models/bar/foo.rb, which it then loads (which makes Bar::Foo available, but not Foo), then throws the exception because Foo isn't available.

The solution in this case was to remove the autoload_paths setting, so that Rails would not find the wrong file to load for the root-level constant.

于 2012-09-23T00:53:42.447 に答える
2

Turns out that this line in config/applications.rb was the problem:

 config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]

With explicitly set autoload, Rails got confused; rather than look under models/ by namespacing appropriately, it looked at the first autoload file it had (which was, mistakenly, models/bar/foo.rb) and found (true) that it failed to define Foo (it defines Bar::Foo).

So evidently Rails 3 already knows to look in models/ subdirs for namespaced models.

Thanks to Antiarc on freenode #RubyOnRails for helping figure this out.

于 2012-09-23T00:52:16.067 に答える