【问题标题】:CollectionProxy vs AssociationRelationCollectionProxy vs AssociationRelation
【发布时间】:2016-02-14 11:48:58
【问题描述】:

我想知道ActiveRecord::Associations::CollectionProxyActiveRecord::AssociationRelation 之间的区别。

class Vehicle < ActiveRecord::Base
  has_many :wheels
end

class Wheel < ActiveRecord::Base
  belongs_to :vehicle
end

如果我这样做:

v = Vehicle.new

v.wheels # =&gt; #&lt;ActiveRecord::Associations::CollectionProxy []&gt;

v.wheels.all # =&gt; #&lt;ActiveRecord::AssociationRelation []&gt;

我不知道它们之间有什么区别以及为什么要这样实现?

【问题讨论】:

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord ruby-on-rails-5


【解决方案1】:

ActiveRecord::Relation 是在转换为查询并执行之前的简单查询对象,另一方面,CollectionProxy 更复杂一些。

首先你得到关联扩展,你可能看到了像这样的东西,假设一个书店模型有很多书

class Store < ActiveRecord::Base
  has_many :books do
    def used
      where(is_used: true)
    end
  end
end

通过这种方式,您可以使用如下所示的语法来调用商店中的旧书

Store.first.books.used

但这是最基本的用途,你可以使用集合代理中暴露给你的属性,即ownerreflectiontarget

所有者

owner 提供对持有关联的父对象的引用

反射

reflection 对象是ActiveRecord::Reflection::AssocciationReflection 的一个实例,包含关联的所有配置选项。

目标

target 是关联集合对象(或has_onebelongs_to 时的单个对象)。

使用这些方法,您可以在关联扩展中执行一些条件,例如,如果我们有一个博客,我们会将所有已删除帖子的访问权限授予管理员用户(我知道的蹩脚示例)

Class Publisher < ActiveRecord::Base
  has_many :posts do
    def deleted
      if owner.admin?
        Post.where(deleted: true)
      else
        where(deleted: true)
      end
    end
  end
end

您还可以访问另外两个方法resetreload,第一个(reset)清除缓存的关联对象,第二个(reload)更常见,用于reset 然后从数据库中加载关联的对象。

我希望这能解释拥有 CollectionProxy 类会如何如此有用

【讨论】:

    【解决方案2】:

    好的。区别很简单。

    根据您的示例进行解释:

    v.wheels 中的关联代理有:

    • v 中的对象为@owner;
    • 作为@target 的轮子集合;
    • 而@reflection 对象代表一个:has_many 宏。

    来自docs

    Active Record 中的关联代理是@owner 之间的中间人 和@target。 直到需要时才会加载@target 对象。

    v = Vehicle.new
    v.wheels # we are not sending any methods to @target object (collection of wheels)
    # => #<ActiveRecord::Associations::CollectionProxy []>
    

    这意味着,只要您调用@target 对象(在我们的例子中包含wheels 的集合)上的任何方法,@target 就会被加载,它会变成ActiveRecord_AssociationRelation

    v.wheels.all # sending the `all` method to @target (wheels)
    # => #<ActiveRecord::AssociationRelation []>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多