为什么 Rails 模型关联结果不是自然的 ActiveRecord::Relations? [英] Why are Rails model association results not naturally ActiveRecord::Relations?
问题描述
我使用的是 Rails 3.2.0
I'm using 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 对象,但检查该类会给出不同的类型.
Certain evaluations act upon an ActiveRecord::Relation object, but inspecting the class gives a different type.
特别是,当使用 merge
连接多个查询时,这会破坏构建延迟加载的查询.
Particularly, this breaks building lazy-loaded queries when using merge
to concat multiple queries.
推荐答案
它是一个 ActiveRecord::Relation
,但 Rails 故意对你撒谎.您可以在方法调用中看到这一点,并通过调用 ancestors
继续看到它,其中包括大量 ActiveRecord 类:
It is an ActiveRecord::Relation
, but Rails is intentionally lying to you. You can see this already in the method calls, and continue to see it by calling ancestors
, which includes a slew of ActiveRecord classes:
c1.articles.ancestors.select { |c| c.to_s =~ /ActiveRecord/ }.size #=> 35
这表明它非常不是一个Array
.
发生这种情况是因为您在调用 c1.articles
时返回的是 ActiveRecord::Associations::CollectionProxy
*, 取消定义class
(以及许多其他方法)).这意味着 class
通过 它的method_missing
,其中将其发送到 target
.可以看到,这里的target
类实际上就是Array
:
This happens because what you’re getting back when calling c1.articles
is an ActiveRecord::Associations::CollectionProxy
*, which undefines class
(along with many other methods). This means that class
gets delegated via its method_missing
, which sends it to target
. As we can see, the class of target
here is, in fact, Array
:
c1.articles.target.class #=> Array
这就是 c1.articles.class
的来源.尽管如此,它是一个ActiveRecord::Relation
.
That is where c1.articles.class
comes from. Nevertheless, it is an ActiveRecord::Relation
.
<子>* 我们可以通过在相关对象上调用 Ruby 的原始 class
方法来验证它确实是一个 ActiveRecord::Associations::CollectionProxy
:Object.instance_method(:class).bind(c1.articles).call
.这是一个很好的技巧来验证对象没有试图假装属于不同的类.
* We can verify that it is indeed an ActiveRecord::Associations::CollectionProxy
by calling Ruby’s original class
method on the object in question: Object.instance_method(:class).bind(c1.articles).call
. This is a nice trick to verify that the object is not trying to pretend to be of a different class.
这篇关于为什么 Rails 模型关联结果不是自然的 ActiveRecord::Relations?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!