通过三个关联查询where方法

Query for where method through three associations

我有三个模型:

Invitation.rb

belongs_to :department

Department.rb

belongs_to :organisation
has_many :invitations

Organisation.rb

has_many :departments

组织 table 有 tag 字段。

我需要编写一个查询来搜索邀请,其组织有一个 tag 字段,内容为 'First tag'

像这样:

Invitation.joins(:department).joins(:organisation).where(tag: 'First tag')

但我不知道如何构建这样的查询。

Invitation.joins(department: :organisation).where(organisations: { tag: 'First tag' })

为什么?因为对于 "reach" 组织 table 的邀请,您可以使用部门之间的关系 table。

Table.joins(...).joins(...)

是"joining"两倍table,你需要的是参考部门和组织之间的关系。你可以这样做:

{ department: :organisation }

将其传递给 join 会在接收器中使用 departments 加载 JOIN 子句,并在 departments 中使用 organisations.

注意 where 子句可以用作 { organisations: { tag: ... } }["organisations.tag = ?", ...],它们可以互换使用。您使用什么只是您或您同事的偏好问题。

要在不更改模型的情况下完成您正在尝试做的事情,您应该将散列传递给连接方法,如下所示:

Invitation.joins(department: :organisation).where(organisations: { tag: 'First tag' })

这告诉 ActiveRecord 使用邀请模型中定义的部门关联部门模型中的组织关联

为了让您的生活更轻松一些,您可以像这样添加 has_many through 关联:

class Invitation < ApplicationRecord
  belongs_to :department
  has_one :organisation, through: :department
end

class Department < ApplicationRecord
  belongs_to :organisation
  has_many :invitations, inverse_of: :department
end

class Organisation
  has_many :departments, inverse_of: :organisation
  has_many :invitations, through: :departments
end

现在您可以在组织上使用邀请关系,如下所示:

Invitation.joins(:organisation).where(tag: 'First tag')

要查看 sql(例如在控制台中),您可以使用 #to_sql 方法:

Invitation.joins(:organisation).where(tag: 'First tag').to_sql

最后,如果您使用范围(并且不喜欢必须在其中指定 table 的 where 方法中的散列),您可以使用 "scope" 并按如下方式合并:

class Organisation
  class << self
    def just_tagged
      where(tag: 'First tag')
    end
  end
end

现在您可以使用 merge:

在查询中引用范围
Invitation.joins(:organistion).merge(Organisation.just_tagged)