按数组中的所有 id 过滤

Filter by all ids in an array

我有两个模型,都具有 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

例如,在电影索引页面上,我希望能够按流派进行过滤。对于过滤器表单,我有一个多 select 流派框,当提交时发送一个 id 数组。

如何使用 Active Record 找到匹配数组中所有这些 ID 的电影,而不是仅匹配任何 ID 的电影?例如,如果用户 select 是恐怖片和喜剧片,它应该过滤到同时是恐怖片和喜剧片的电影,而不仅仅是任何恐怖片或任何喜剧片。

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

以上示例查找任何一部恐怖片或喜剧片。

通过使用 joinsgrouphaving 解决了这个问题。

ids = params[:genres]

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

这基本上会过滤掉重复的匹配项,return 只会过滤掉与原始数组计数结果数量相同的电影。这意味着如果数组计数为 3,则只有从原始 joins 查询中获得 3 个结果的电影才会匹配。