为什么 Rails 模型关联结果不是自然的 ActiveRecord::Relations? [英] Why are Rails model association results not naturally ActiveRecord::Relations?

查看:15
本文介绍了为什么 Rails 模型关联结果不是自然的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆