Найти всех родителей, у которых все дочерние записи в точности совпадают с заданным списком, в котором есть множество через ассоциацию в Rails - PullRequest
0 голосов
/ 04 октября 2018

У меня есть следующие отношения

class Invoice
  has_many :entries
  has_many :price_matrixes, through: entries
end

class Entry
  belongs_to :invoice
  belongs_to :price_matrix
end

class PriceMatrix
  has_many :entries
  has_many :invoices, through: entries
end

Теперь у меня есть набор идентификаторов price_matrix, например [1, 2], и я хочу найти все счета-фактуры, в которых ТОЛЬКО указана только эта две ценовые матрицы.

Примечание: пробовал это Invoice.includes(:price_matrixes).where(price_matrixes: {id: [1, 2]}), но это должно вернуть запись, даже если один из идентификаторов из списка будет совпадать.

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Вы можете использовать inner join и тот же where clause, который вы пробовали.

Invoice
  .joins('INNER JOIN entries on entries.invoice_id = invoices.id')
  .where(entries: { price_matrix_id: [1, 2] })
0 голосов
/ 04 октября 2018

Задача легко решается простым SQL.Предполагая, что вы используете PostgreSQL 9+, это SQL-запрос для получения идентификаторов счетов, которые соответствуют вашему условию (имеют ТОЧНО ценовые матрицы только с идентификаторами [1, 2]):

SELECT I.id
FROM invoices I  
  JOIN entries E ON E.invoice_id = I.id
GROUP BY I.id
HAVING array_agg(E.price_matrix_id ORDER BY E.price_matrix_id ASC) = ARRAY[1,2];

Здесь мы присоединяемся invoicesи entries, группировать результаты по invoice.id и фильтровать только те из них, которые дали price_matrix_ids.Обратите внимание, что выражение ARRAY[1,2] должно содержать price_matrix_ids, отсортированное в порядке возрастания.

Демонстрация в сети: http://rextester.com/TAEUU9220

Возвращаясь к Ruby, приведем код:

price_matrix_ids = [1,2].sort

Invoice.joins(:entries).having("array_agg(entries.price_matrix_id ORDER BY entries.price_matrix_id ASC) = ARRAY[#{price_matrix_ids.join(',')}]").group('invoices.id')
0 голосов
/ 04 октября 2018

Рельсы> = 3,2

Invoice.includes(:price_matrix).where(price_matrix: {id: [1, 2]})

Рельсы <3,2 </p>

Invoice.joins(:price_matrix).where("price_matrix.id IN [1, 2]")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...