Name Clash with Top Level constant when autoloading with Rails

北城余情 提交于 2019-12-24 00:48:53

问题


I'm having a class Dog in app/models/dog.rb and another class Services::My::Deeply::Nested::Dog in app/services/my/deeply/nested/dog.rb.

Now in Services::My (app/services/my.rb), I have a reference to one of the following (no need to distinguish, since the behaviour is exaclty the same in all situations):

  • Deeply::Nested::Dog
  • Services::My::Deeply::Nested::Dog
  • ::Services::My::Deeply::Nested::Dog

No matter which of the above I choose, I always get the following error message:

services/my.rb: warning: toplevel constant Dog referenced by Services::My::Deeply::Nested::Dog

Also, my deeply nested Dog never even gets seen by the interpreter (I found out by using puts and syntax errors, nothing happens).

Possible workarounds (which I all don't like) are:

  • Rename one of the Dog classes
  • Run with RAILS_ENV=production in order to disable autoloading and use eager loading instead
  • require_dependency that points to the deeply nested dog

As a computer scientist, I find none of the above workarounds satisfactory. I would like to understand why my deeply nested Dog is not found without workaround and find out what the state-of-the-art Ruby / Rails solution would be for this problem.

Thanks a lot in advance.


回答1:


app/services/my/deeply/nested/dog.rb should define My::Deeply::Nested::Dog and not Services::My::Deeply::Nested::Dog, for the same reason that app/models/dog.rb doesn't define Models::Dog but just Dog.

With :

#app/services/my/deeply/nested/dog.rb                                                       
module My
  module Deeply
    module Nested
      class Dog
        puts "I'm in %s" % __FILE__
        puts Module.nesting.inspect
      end
    end
  end
end

and

# app/models/dog.rb
class Dog
  puts "I'm in %s" % __FILE__
  puts Module.nesting.inspect
end

and

# app/services/my.rb
module My
  puts "I'm in %s" % __FILE__
  puts Module.nesting.inspect
  Dog
  My::Deeply::Nested::Dog
end

You get :

Loading development environment (Rails 5.0.0.1)
2.3.1 :001 > My
I'm in /home/ricou/www/new_rails_5_app/app/services/my.rb
[My]
I'm in /home/ricou/www/new_rails_5_app/app/models/dog.rb
[Dog]
I'm in /home/ricou/www/new_rails_5_app/app/services/my/deeply/nested/dog.rb
[My::Deeply::Nested::Dog, My::Deeply::Nested, My::Deeply, My]
 => My 


来源:https://stackoverflow.com/questions/40928631/name-clash-with-top-level-constant-when-autoloading-with-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!