Rails中的Namespaced模型生成NameError:未初始化的常量
我有这样的文件夹结构:
app/ models/ bar/ foo.rb connection.rb foo.rb
connection.rb
是一个用于连接到另一个数据库的“抽象类”,因此:
class Bar::Connection < ActiveRecord::Base self.abstract_class = true establish_connection "outsidedb_#{Rails.env}" end
bar/foo.rb
用于从foos
访问foos
表,因此:
class Bar::Foo < Bar::Connection end
并且foo.rb
用于从应用程序的db访问foos
表,因此:
class Foo < ActiveRecord::Base end
从rails控制台,如果我做Foo.first
或Bar::Foo.first
事情就像我期望的那样,我分别从应用程序db和外部数据库的foos
表中获得第一个条目。
但是,如果我尝试从bar/foo.rb
访问Foo
,我会得到以下结果:
class Bar::Foo works Foo.first #=> NameError: uninitialized constant Bar::Foo::Foo end def self.other_test Foo.parent #=> Object Foo.superclass #=> ActiveRecord::Base Object::Foo.first #=> works ActiveRecord::Base::Foo.first #=> works, but with "warning: toplevel constant # Foo referenced by ActiveRecord::Base::Foo end end
我显然可以让事情有效,但我正在寻找一个更健全的理解正在发生的事情。 我假设我在Ruby的常量/类评估和Rail的内置自动加载之间缺少某些东西……
- 什么是
.parent
返回(不是’父’类)? - 为什么我在
.test
得到错误,但是我没有在rails控制台中得到它? - 为什么
Object::Foo
似乎有效? 这是正确的做法吗? - 为什么
ActiveRecord::Base::Foo
工作,但有警告? - 有没有更多的rails方式来做我已经完成的事情,而不只是重命名我的一个
foo.rb
类?
我正在使用Rails '3.2.13'
和Ruby 1.9.3-p194
,所以你知道!
您的问题可以解决
::Foo.first
这里::Foo
表示顶级命名空间中的类Foo
。
你的问题来自于你正在使用的命名空间( Bar
)中有另一个Foo
类。所以你应该是明确的。
至于为什么Object::Foo
工作(带警告)的问题,它是Ruby中名称查找的(较少)已知行为。 有关详细信息,请参阅此文章。
这里有一些关于.parent
方法的文档,它可以帮助回答你的第一个问题: http : .parent
。 向下滚动到第3.3节,了解相关部分。
.parent
方法附带Active Support,它为Ruby on Rails组件提供Ruby扩展。 .parent
方法是Modules的扩展,它返回包含当前类的模块的名称。 所以,如果你做了Bar::Foo.parent
,返回值应该是Bar
。
但是,当类没有封闭模块时,返回值将默认为Object
。 当你执行Foo.parent
时会发生这种情况,因为Foo
在这里指的是不在Bar
命名空间中的Foo
类。
相关的Rails魔术: https : //github.com/rails/rails/blob/c9bbac46ddfc68caff6cd8a95c8d0fd045bd9201/activesupport/lib/active_support/core_ext/module/introspection.rb