Named Rails model conflicting with a model other than names

I have two classes in rails 3.2.6:

  • Foo class in /foo.rb models (found in the foos table by default)
  • class Bar :: Foo in models /bar/foo.rb (which sets self.table_name to bar_foos )

When I go to the console, I get:

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

What's wrong?

+4
source share
2 answers

We solved this in IRC, but the main problem is that there is a set of config.autoload_paths glob that included models/** as boot paths.

The Rails autoloader iterates the download paths and binds to the constant name. When he finds a file that exists, he tries to download it, then throws an exception if the constant is not available.

So what happens, Rails had a list of loading paths, for example:

 /models/bar/ /models/ 

He repeated the paths and found a match in /models/bar/foo.rb , which then loads (which makes Bar::Foo accessible but not Foo ) and then throws an exception because Foo not available.

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

+5
source

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

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

Rails is confused with explicitly installed startup; instead of looking under models / by placing names accordingly, he looked at the first startup file, which he (by mistake, models /bar/foo.rb), and found (true) that he could not determine Foo (he defines Bar :: Foo).

Thus, it is obvious that Rails 3 already knows how to search in models / sub-frames for models with names.

Thanks to Antiarc on freenode #RubyOnRails to help figure this out.

+2
source

Source: https://habr.com/ru/post/1434721/


All Articles