ActiveRecord查找具有has_many关系状态的某些计数的所有记录

时间:2017-11-21 19:03:36

标签: ruby-on-rails activerecord one-to-many

我有Post模型和Comment模型。一个Post has_many Comment。每个Comment都有一个status属性,从技术上讲,它是数据库(Postgres)级别的整数列,但在ActiveRecord模型声明级别列为枚举:enum status: [:draft, :published, :removed]。我想构建一个ActiveRecord查询来查找:

所有Post模型都有:

  1. 0相关评论模型
  2. 发布所有状态的评论模型
  3. 我想我找到了满足第一个约束的方法:

    Post.includes(:comments).where(comments: {id: nil})
    

    但是,第二个限制因素给了我麻烦。我可以找到所有至少一个已发布状态的评论的帖子,但不包含以及所有已发布状态的评论:

    Post.includes(:comments).where(comments: {status: :published})
    

    我需要一种方法来使第二个约束正常工作并组合两个搜索(如果可能的话)。

    我希望我不需要使用普通的SQL来执行此操作

1 个答案:

答案 0 :(得分:1)

您可以翻转查询以避免进入SQL。而不是搜索发布所有评论的帖子,搜索没有评论草稿或删除的帖子:

Post.where('id NOT IN (?)', Post.select(:id).includes(:comments).where(comments: {status: [:draft, :removed]}))

从OP编辑:

SO不允许我在回复中提供足够的字符来解释我如何从您的查询中找到有效的字符。如果这是错误的方法,请随时纠正我。我只想把这些东西包括给子孙后代......

首先,谢谢。使用子查询来翻转逻辑以及此示例查询的想法让我找到了一个有效的解决方案。以下是这样的情况,以防将来有人来到这里:

您的确切查询返回了此AR错误:

  

ActiveRecord :: StatementInvalid:PG :: SyntaxError:ERROR:子查询列太多

因此,我删除了select(:id)并在子查询中添加了pluck(:id)来修复错误。

然后,由于某种原因,where('id NOT IN (?), [])总是清空结果数组/关系,即使黑名单的ID数组为空,如该示例所示。所以最后,我结束了这个问题解决了我的问题:

Post.where.not(id: Post.includes(:comments).where(comments: {status: [:draft, :removed]}).pluck(:id))