假设我有以下两个对象:
first_name_relation = User.where(:first_name => 'Tobias') # ActiveRecord::Relation
last_name_relation = User.where(:last_name => 'Fünke') # ActiveRecord::Relation
是否可以组合这两个关系来生成一个包含两个条件的ActiveRecord::Relation
对象?
注意:我知道我可以链接这些行为,我真正感兴趣的是我有两个单独的ActiveRecord::Relation
对象。 < / p>
答案 0 :(得分:171)
如果要使用AND
(十字路口)进行组合,请使用merge
:
first_name_relation.merge(last_name_relation)
如果您想使用OR
(联合)进行组合,请使用or
(在ActiveRecord 5+中提供,或在4.2中通过where-or backport提供):
first_name_relation.or(last_name_relation)
答案 1 :(得分:35)
Relation对象可以转换为数组。这无法在之后使用任何ActiveRecord方法,但我不需要。我这样做了:
name_relation = first_name_relation + last_name_relation
Ruby 1.9,rails 3.2
答案 2 :(得分:18)
merge
实际上不像OR
那样有用。这只是交集(AND
)
我努力解决这个问题,将ActiveRecord :: Relation对象合并为一个,但我找不到任何有用的解决方案。
我没有从这两个集合中搜索创建联合的正确方法,而是专注于集合的代数。您可以使用De Morgan's law
以不同的方式执行此操作ActiveRecord提供合并方法(AND),您也可以使用not method或none_of(NOT)。
search.where.none_of(search.where.not(id: ids_to_exclude).merge(search.where.not("title ILIKE ?", "%#{query}%")))
你在这里(A u B)'= A'^ B'
更新: 上述解决方案适用于更复杂的情况。 在你的情况下,像这样就足够了:
User.where('first_name LIKE ? OR last_name LIKE ?', 'Tobias', 'Fünke')
答案 3 :(得分:14)
通过使用Rails的内置 Arel ,即使在很多奇怪的情况下,我也能够做到这一点。
User.where(
User.arel_table[:first_name].eq('Tobias').or(
User.arel_table[:last_name].eq('Fünke')
)
)
使用Arel的或合并两个ActiveRecord关系。
如此处所示,合并对我不起作用。它从结果中删除了第二组关系对象。
答案 4 :(得分:13)
有一个名为active_record_union的宝石 这可能就是你要找的东西。
它的示例用法如下:
current_user.posts.union(Post.published)
current_user.posts.union(Post.published).where(id: [6, 7])
current_user.posts.union("published_at < ?", Time.now)
user_1.posts.union(user_2.posts).union(Post.published)
user_1.posts.union_all(user_2.posts)
答案 5 :(得分:7)
这就是我处理&#34;的方式。如果你使用pluck获取每个记录的标识符,将数组连接在一起然后最终对这些连接的id进行查询:
transaction_ids = @club.type_a_trans.pluck(:id) + @club.type_b_transactions.pluck(:id) + @club.type_c_transactions.pluck(:id)
@transactions = Transaction.where(id: transaction_ids).limit(100)
答案 6 :(得分:6)
如果你有一组activerecord关系,想要将它们全部合并,你可以
array.inject(:merge)
答案 7 :(得分:0)
蛮力:
first_name_relation = User.where(:first_name => 'Tobias') # ActiveRecord::Relation
last_name_relation = User.where(:last_name => 'Fünke') # ActiveRecord::Relation
all_name_relations = User.none
first_name_relation.each do |ar|
all_name_relations.new(ar)
end
last_name_relation.each do |ar|
all_name_relations.new(ar)
end
答案 8 :(得分:0)
我偶然发现了这个问题,并且普遍接受的回应从未对我有用。
在接受的答案中提出的解决方案似乎最有效:
first_name_relation.or(last_name_relation)
但我永远无法让这个工作,并且总是会收到一个未定义的方法&#39; &#39;或&#39;的错误。
我的解决方案:
combined_relation = first_name_relation + (last_name_relation - first_name_relation)
这基本上给出了原始查询之间UNION的结果,并且关系对象仍然是正确的ActiveRecord对象。
这与@thatmiddleway提供的答案类似,但我需要添加减法来获取DISTINCT对象集合。这确实将组合的集合转换为ARRAY,但我仍然可以在每个&#39;中的各个实例上调用模型方法。在我看来,迭代器解决了我的问题。
这是我的第一个StackOverflow答案(喘气!),所以我欢迎你的反馈!