Rails: 如何与 has_many 相关的 table 进行高级查询?

Rails: How do I advanced query with has_many related table?

我有两个模型。

class Revision < ApplicationRecord
  has_many :revision_approvals
end

class RevisionApproval < ApplicationRecord
  belongs_to :revision
end

修订可以有很多revision_approvals。 RevisionApproval 具有角色(字符串)和决策(枚举 - 整数)字段。角色可以是 process_responsible 或 process_coordinator。 process_coordinator 角色高于 process_responsible 角色。 process_coordinator 的决定需要修订批准。如果 process_coordinator 还没有做出任何决定,则修订保持待批准状态。 如果revision_approval的角色是process_coordinator,根据process_coordinator的决定,revision的状态从pending approval变为approved或rejected。 我想要具有待批准状态的修订。如何通过单个查询执行此操作?

TL;DR

属于修订版的

revision_approvals 不应具有 process_coordinator 角色。这包括没有任何 revision_approval.

的修订

例如:

修订 table:

revision_id has any revision_approval?
577 true
576 false
16 true
566 true
384 true

revision_approvals table:

revision_id role decision
577 process_responsible 0
16 process_responsible 1
16 process_coordinator 1
566 process_responsible 1
384 process_coordinator 0

查询应 return id 为 566、576、577 的修订。

下面的查询return是我想要的记录。过了一会儿如果没有更好的答案,我会添加这个作为答案。

Revision.where.not(
  id: Revision.joins(:revision_approvals)
              .where(revision_approvals: { role: :process_coordinator })
)

如果您想要所有修订:

Revision.all

如果您想要具有角色“process_responsible”的角色 revision_approval 的修订:

Revision.joins(:revision_approvals).where(role: "process_responsible")

Revision.joins(:revision_approvals).where("revision_approvals.role = ?",  "process_responsible")

如果您想要具有角色“process_responsible”和 process_responsible 0:

的角色 revision_approval 的修订
Revision.joins(:revision_approvals).where("revision_approvals.role = ? AND revision_approvals.decision = ?",  "process_responsible", 0)

没有 revision_approval 的修订:

Revision.includes(:revision_approval).where(revision_approvals: { id: nil })

此 returns revisions_approval 不是 process_coordinator

的所有修订
Revision.joins(:revision_approvals).where("revision_approvals.role != ?",  "process_coordinator")

下面查询returns我要的记录

Revision.where.not(
  id: Revision.joins(:revision_approvals)
              .where(revision_approvals: { role: :process_coordinator })
)