使用Rails自动加载时名称与顶级常量冲突

时间:2016-12-02 09:21:15

标签: ruby-on-rails ruby constants autoload toplevel

我在Dog中有一个课程app/models/dog.rb,在Services::My::Deeply::Nested::Dog中有另一个课程app/services/my/deeply/nested/dog.rb

现在在Services :: My(app / services / my.rb)中,我引用了以下内容之一(无需区分,因为在所有情况下行为都是相同的):

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

无论我选择上述哪一项,我都会收到以下错误消息:

  

services / my.rb:警告:由Services::My::Deeply::Nested::Dog

引用的toplevel常量Dog

另外,我深深嵌套的狗甚至从未被翻译看到(我发现使用了放置和语法错误,没有任何反应)。

可能的解决方法(我都不喜欢)是:

  • 重命名其中一个Dog类
  • 使用RAILS_ENV = production运行以禁用自动加载并使用急切加载
  • require_dependency指向深层嵌套的狗

作为一名计算机科学家,我发现上述解决方法都不令人满意。我想了解为什么没有解决方法就找不到我深深嵌套的Dog,并找出最先进的Ruby / Rails解决方案对于这个问题的原因。

提前多多感谢。

1 个答案:

答案 0 :(得分:1)

app/services/my/deeply/nested/dog.rb应该定义My::Deeply::Nested::Dog而不是Services::My::Deeply::Nested::Dog,原因与app/models/dog.rb不定义Models::Dog但仅Dog相同}。

使用:

#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

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

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

你得到:

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