【问题标题】:Is it possible to get the ActiveRecord::Relation object for an association是否可以获得关联的 ActiveRecord::Relation 对象
【发布时间】:2011-05-09 18:27:39
【问题描述】:
  1. 关联方法(例如has_manybelongs_to 定义的那些方法)是否使用ActiveRecord::Relation

  2. 如果可以,是否可以得到正在使用的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 的理由应该很明显:这是因为我想链接现有的关联并操纵查询以适应不同的目的。

【问题讨论】:

    标签: activerecord ruby-on-rails-3 associations arel


    【解决方案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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-14
          • 1970-01-01
          • 1970-01-01
          • 2020-02-26
          • 1970-01-01
          相关资源
          最近更新 更多