Фильтр по всем идентификаторам в массиве - PullRequest
1 голос
/ 30 мая 2019

У меня есть две модели, обе с отношением has_and_belongs_to_many.

class Movie < ApplicationRecord
  has_and_belongs_to_many :genres
end
class Genre < ApplicationRecord
  has_and_belongs_to_many :movies
end

Так, например, на странице индекса фильма я хочу иметь возможность фильтрации по жанру. Для формы фильтра у меня есть поле выбора жанров, которое при отправке отправляет массив идентификаторов.

Как мне найти фильмы, которые соответствуют ВСЕМ этим идентификаторам в массиве, а не просто любому из идентификаторов, использующих Active Record? Если пользователь выбирает, например, «Ужасы» и «Комедии», ему следует отфильтровать фильмы, которые одновременно являются «Ужасами» и «Комедиями», а не просто фильмы ужасов или комедии.

ids = params[:genres]
Movie.includes(:genres).where(genres: {id: ids})

Приведенный выше пример находит любой фильм ужасов или комедии.

1 Ответ

1 голос
/ 31 мая 2019

Разобрался с помощью joins с group и having.

ids = params[:genres]

Movie.joins(:genres)
  .where(genres: {id: ids})
  .group(:id)
  .having("count(*) = #{ids.count}")

Это, в основном, отфильтровывает дубликаты совпадений и возвращает только фильмы, результаты которых совпадают с исходным количеством массивов. Это означает, что если количество массивов равно 3, совпадут только фильмы, которые имеют 3 результата из исходного запроса joins.

...