我试图了解ActiveRecord Relation合并的工作原理,因为似乎缺少文档和示例。它的文档说它返回调用对象和合并参数“ other”的交集,看起来很简单。
我有一个简单的User类并进行了适当的迁移
class User < ApplicationRecord
...
end
在大多数情况下,似乎合并的行为完全符合我的预期,但是经过检查,合并行为出乎意料。如果我建立没有重叠项的琐碎关系,那么我希望它们的交集将是一个空的Relation
relation1 = User.where(id: 1)
relation2 = User.where(id: 2)
relation1.merge(relation2) # returns Relation containing User with id: 2
relation2.merge(relation1) # returns Relation containing User with id: 1
这很短。我尝试使用的较长版本是使用Pundit来设置用户的策略范围,在这种情况下,属于用户的所有财务帐户。然后,在我的控制器中,我对财务帐户的索引操作按其类型(储蓄,支票,贷方等)进行过滤。因此,我希望用户仅查看属于它们的那些筛选出的财务帐户,这是两个集合的交集:1)所有正在检查帐户的财务帐户,以及2)属于用户的所有财务帐户。因此,似乎合并应该可以解决问题,但是它的工作方式与我预期的不同。
Rails 5.1.6
ruby 2.3.3p222
答案 0 :(得分:0)
据我所知,由于“其他”关系是ActiveRecord关系(与Array相反),因此它并不严格产生交集。而是合并条件。在我的琐碎示例中,由于条件是如此相似(即where(id:?),因此合并过程不会对条件进行AND运算,而是将调用对象的条件替换为参数对象的条件。
解决此问题的一种方法是使用to_a将参数对象转换为Array。在这种情况下,相同的合并函数会计算正确的交点。
relation1 = User.where(id: 1)
relation2 = User.where(id: 2)
relation1.merge(relation2.to_a) # returns an empty Array (note: not a Relation)
缺点是查询未在数据库中完全完成,因此效率较低。
这似乎也可以解释为什么它比我更复杂的合并更能按预期工作。较复杂的合并将具有较复杂的条件,这些条件很少像在较简单的情况下那样足以被覆盖/替换。