首页 > 解决方案 > ActiveRecord .joins() 并在连接模型上使用 .where(),其中 2 个“IN”条件由“OR”连接

问题描述

问题

我有一个Post和一个Comment,我想选择帖子并在包含一个和两个条件的评论上使用一个.joins()和一个。.where()ORIN

我想要产生这个的东西:

SELECT * FROM posts
INNER JOIN comments ON comments.post_id = posts.id
WHERE comments.id IN (1,2,3) OR comments.user_id IN (4,5,6)

我会使用该.or()方法,但它不能使用哈希。

Post.joins(Comment)
  .where({ comments: { id: [1, 2, 3] } })
  .or({ comments: { user_id: [4, 5, 6] } })      # <-- raises exception

可能的解决方案

为了便于阅读,我对此进行了简化。实际上,我需要它来跨数据库适配器工作,所以我会使用Comment.connection.quote_table_nameComment.connection.quote_column_name正确引用表和列名。

ids = [1,2,3]
user_ids = [4,5,6]

clause = ""
clause += Comment.sanitize_sql_for_conditions(["comments.id IN (?)", ids]) if ids.any?
clause += " OR " if ids.any? and user_ids.any?
clause += Comment.sanitize_sql_for_conditions(["comments.user_id IN (?)", user_ids]) if user_ids.any?

Post.joins(Comment).where(clause)

问题

这可行,但似乎应该有更好的方法......有吗?

标签: ruby-on-railsactiverecordrails-activerecord

解决方案


Post我假设你在你的类上有一个评论关系has_many :comments,Rails 足够聪明,知道当你使用.where关系名称时,你会考虑每个评论的 id,然后你可以简单地写下 id。

要使用 OR,您必须使用将用于构造主查询的相同类,它就像 or 中的“子查询”,就像跟随一样。

请尝试使用下一个代码:

Post.joins(:comments)
  .where(comments: [1, 2, 3])
  .or(Post.where('comments.user_id IN ?', [4, 5, 6]))

轨道或:https
://zaiste.net/rails_5_or_operator_active_record/ 加入:https ://apidock.com/rails/ActiveRecord/QueryMethods/joins

编辑

由于在此答案上引用了已知问题,您应该使用原始 SQL,如下所示。

Post.joins(:comments)
  .where('comments.id in ? OR comments.user_id in ?', [1, 2, 3], [4, 5, 6])

原始 sql 中的每个?都将替换为以相同顺序从左到右.where传递的参数。


推荐阅读