是否可以获得关联的 ActiveRecord::Relation 对象

Posted

技术标签:

【中文标题】是否可以获得关联的 ActiveRecord::Relation 对象【英文标题】:Is it possible to get the ActiveRecord::Relation object for an association 【发布时间】:2011-05-09 18:27:39 【问题描述】:

    关联方法(例如has_manybelongs_to 定义的那些方法)是否使用ActiveRecord::Relation

    如果可以,是否可以得到正在使用的ActiveRecord::Relation对象。

我们都知道 Rails 3 在使用Query Interface 创建查询时大量使用ActiveRecord::Relation 对象,并在后台使用Arel::Relation 对象。每当我们使用查询接口的selectjoins等方法时,都会返回一个ActiveRecord::Relation对象。但是,在调用模型的关联方法时,情况似乎并非如此。相反,查询会立即执行并返回关联模型的一个实例或实例数组。

考虑以下模型:

post.rb

class Post < ActiveRecord::Base
  belongs_to :user
end

user.rb

class user < ActiveRecord::Base
  has_many :posts
end

例子:

u = User.first
u.posts

调用u.posts 返回一个帖子数组,而不是ActiveRecord::Relation 的实例。我想知道是否有可能获得被协会使用ActiveRecord::Relation,如果它正在被使用,也许是通过使用Arel::Table

我想要ActiveRecord::Relation 的理由应该很明显:这是因为我想链接现有的关联并操纵查询以适应不同的目的。

【问题讨论】:

【参考方案1】:

通过花时间实际阅读 Edge Guides 文档,我能够在 Section 4.3 has_many Association Reference 中找到一个答案。简而言之,该文档没有说明是否可以获得 ActiveRecord::Relation 对象或是否正在使用 ActiveRecord::Relation 对象,但它确实提供了有关如何重用关联和调整其结果的详细信息。

4.3.1 Methods Added by has_many 部分将 collection.where 列为 has_many 关联添加的方法之一。 4.3.1.11 collection.where(…) 部分显示您可以像使用查询接口的 where 方法一样使用它。更重要的是,它提示对象是延迟加载的,当在集合上使用该方法时,果然返回了一个ActiveRecord::Relation 对象。

u.posts.where("").class  # => ActiveRecord::Relation
u.posts.where("").to_sql # => SELECT `posts`.* FROM `posts` WHERE `posts`.user_id = 1 

诚然,这不是理想的解决方案,但它确实给了我一些我可以摆脱的东西。

【讨论】:

【参考方案2】:

有几分钟我使用了where(nil) hack,然后我脑电波并随机尝试了一些东西:

User.first.posts.scoped

就是这样! :D

是的,Rails + Arel 的文档记录确实很差。期待它成熟到我可以实际查找并获得实际答案的程度。

【讨论】:

爱它。干净多了!我给你检查标记。我同意 Arel 文档。我一直在阅读关于它的碎片和碎片。它看起来非常强大,但如果没有良好的文档,它也会很烦人。 :) 有没有办法在我制作的自定义数组上调用.scoped (答案是否定的:scoped 只对***类有意义:/) 有趣的是,.scoped 甚至适用于 has_and_belongs_to_many,否则它会返回一个数组。 .scoped 已折旧【参考方案3】:

在 Rails 4 中,使用 .scope.spawn 而不是 CollectionProxy 来访问关系对象。请参阅documentation。

【讨论】:

【参考方案4】:

ActiveSupport::Concern 中,您不能调用私有方法spawn 或使用scopescoped

我需要使用它。

where(true)

【讨论】:

以上是关于是否可以获得关联的 ActiveRecord::Relation 对象的主要内容,如果未能解决你的问题,请参考以下文章

为啥它可以获得新生成地址的关联帐户?

是否可以使用 findAll() 创建查询并通过使用来自 pivot 的 ForeignKey(关系多对多)获得过滤结果?

获取 Mongoose 模型的(关联)数组

IRelationalOperator接口

将 IP 地址与国家/地区相关联[关闭]

如何获得 smooth.spline 的置信区间?