我使用Rails 3.2.0
比方说,我有:
class Comment < ActiveRecord::Base
has_many :articles
end
c1 = Comment.last
然后
c1.articles.class
# => Array
c1.articles.where('id NOT IN (999999)').class
# => ActiveRecord::Relation
为什么关联不是一个类型的结果ActiveRecord::Relation
?
这显然是/是在一些点 :
c1.articles.to_orig
# undefined method `to_orig' for #<ActiveRecord::Relation:0x007fd820cc80a8>
c1.articles.class
# => Array
某些评估作用于一个ActiveRecord :: Relation对象,但检查类给出了不同的类型。
特别是,这打破了当使用楼宇延迟加载查询merge
到Concat的多个查询。
这是一个ActiveRecord::Relation
,但Rails的是故意骗你的 。 你可以已经在方法调用看到这一点,并继续通过调用看到它ancestors
,它包括的ActiveRecord类的转换:
c1.articles.ancestors.select { |c| c.to_s =~ /ActiveRecord/ }.size #=> 35
这表明,它是非常不是一个Array
。
这是因为你要回到什么时候打电话c1.articles
是ActiveRecord::Associations::CollectionProxy
*,其中取消定义class
(有许多其他方法一起)。 这意味着class
被通过委托其method_missing
,这将其发送到target
。 正如我们所看到的,阶级的target
在这里,事实上, Array
:
c1.articles.target.class #=> Array
这就是c1.articles.class
从何而来。 然而,这是一个ActiveRecord::Relation
。
* 我们可以验证它确实是一个ActiveRecord::Associations::CollectionProxy
通过调用Ruby的原始class
的方法有问题的对象: Object.instance_method(:class).bind(c1.articles).call
。 这是一个很好的技巧,以验证对象是不是想假装自己是不同类的。
因为当你定义的关联,它在你的模型地方:
def #{name}(*args)
association(:#{name}).reader(*args)
end
.reader()返回AssociationProxy,其去除的.class方法和代表未知的方法通过.method_missing到@target。
文章来源: Why are Rails model association results not naturally ActiveRecord::Relations?