Запрос метода where через три ассоциации - PullRequest
1 голос
/ 22 января 2020

У меня есть три модели:

Invitation.rb

belongs_to :department

Department.rb

belongs_to :organisation
has_many :invitations

Organisation.rb

has_many :departments

Таблица организации содержит поле tag.

Мне нужно написать запрос для поиска приглашений, для организации которого есть поле tag с содержанием «Первый тег»

Что-то вроде это:

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

Но я не знаю, как создать такой запрос.

Ответы [ 2 ]

2 голосов
/ 22 января 2020
Invitation.joins(department: :organisation).where(organisations: { tag: 'First tag' })

Почему? Поскольку для «доступа» к таблице организаций из приглашений вы можете использовать связь между таблицами отделов.

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

«Соединяет» дважды одну и ту же таблицу, вам нужно указать ссылку на отношения между отделами и организациями. , То, что вы можете сделать это следующим образом:

{ department: :organisation }

Передача этого для присоединения загружает предложение JOIN в получателе с departments и в departments с organisations.

Обратите внимание, где Предложение может использоваться как { organisations: { tag: ... } } или ["organisations.tag = ?", ...], они могут использоваться взаимозаменяемо. То, что вы используете, - это вопрос ваших или ваших коллег.

1 голос
/ 22 января 2020

Чтобы сделать то, что вы пытаетесь сделать, не изменяя свои модели, вы должны передать ha sh методу joins следующим образом:

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

Наконец, если вы используете область (и вам не нравится ха sh в методе where, в котором вы должны указать таблицу), вы можете использовать «область» и объединить следующим образом:

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

Теперь вы можете ссылаться на область в вашем запросе, используя merge:

Invitation.joins(:organistion).merge(Organisation.just_tagged)
...