我有一个像这样的文件夹结构:
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
访问outsidedb
表格,因此:
class Bar::Foo < Bar::Connection
end
foo.rb
用于从应用程序的数据库访问foos
表,所以:
class Foo < ActiveRecord::Base
end
如果我执行Foo.first
或Bar::Foo.first
,那么从rails控制台执行的操作就像我期望的那样,我从app db的foos
表中获取第一个条目db,分别。
但是,如果我尝试从Foo
内访问bar/foo.rb
,我会收到以下信息:
class Bar::Foo < Bar::Connection
def self.test
Bar::Foo.first #=> 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
有效,但有警告?foo.rb
类之一,还有更多的方法可以完成我的工作吗?我正在Rails '3.2.13'
和Ruby 1.9.3-p194
,只是你知道!
答案 0 :(得分:2)
您的问题可以通过
解决::Foo.first
此处::Foo
表示顶级命名空间中的类Foo
。
你的问题来自于你正在使用的命名空间(Foo
)中有另一个Bar
类。所以你应该是明确的。
关于为什么Object::Foo
有效(带警告)的问题,它是Ruby中名称查找的(较少)已知行为。有关详细信息,请参阅this文章。
答案 1 :(得分:1)
以下是有关.parent
方法的一些文档,可帮助回答您的第一个问题:http://guides.rubyonrails.org/active_support_core_extensions.html#extensions-to-module-parents。向下滚动到第3.3节,了解相关部分。
.parent
方法附带Active Support,它为Ruby on Rails组件提供Ruby扩展。 .parent
方法是Modules的扩展,它返回包含当前类的模块的名称。因此,如果您执行了Bar::Foo.parent
,则返回值应为Bar
。
但是,当类没有封闭模块时,返回值将默认为Object
。这是Foo.parent
执行时发生的事情,因为此处Foo
指的是不在Foo
命名空间中的Bar
类。