为什么Rails的模型关联结果不自然的ActiveRecord ::关系?(Why are Rail

2019-07-17 15:49发布

我使用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的多个查询。

Answer 1:

这是一个ActiveRecord::Relation ,但Rails的是故意骗你的 。 你可以已经在方法调用看到这一点,并继续通过调用看到它ancestors ,它包括的ActiveRecord类的转换:

c1.articles.ancestors.select { |c| c.to_s =~ /ActiveRecord/ }.size  #=> 35

这表明,它是非常不是一个Array

这是因为你要回到什么时候打电话c1.articlesActiveRecord::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 这是一个很好的技巧,以验证对象是不是想假装自己是不同类的。



Answer 2:

因为当你定义的关联,它在你的模型地方:

def #{name}(*args)
  association(:#{name}).reader(*args)
end

.reader()返回AssociationProxy,其去除的.class方法和代表未知的方法通过.method_missing到@target。



文章来源: Why are Rails model association results not naturally ActiveRecord::Relations?