我不能确定正确的术语,所以我无法找到任何帮助。
使用Rails 4我通过film_tags在Film和Tag之间有很多关系。我想将电影的范围仅限于返回包含一组标签的电影。例如,动作和喜剧都是标签,我想搜索具有这两者的电影。目前,我的系统无意中发生了“或”或“搜索,以便它返回所有有动作或喜剧的电影:
薄膜:
scope :includes_tags, ->(tags) {joins(:film_tag).merge(FilmTag.tags(tags))}
FilmTag:
scope :tags, ->(tags) {where(['film_tags.tag_id IN (?)',tags.map(&:id)])}
是否可以通过这两种标签进行过滤,以便我可以继续链接范围?
答案 0 :(得分:1)
您可以使用group
和having
语句来构建这样的范围(未经测试):
class Film < ActiveRecord::Base
scope :includes_tags, ->(tags) do
joins(:film_tags).merge(FilmTag.tags(tags))
.group("films.id")
.having("count(film_tags.id) = ?", tags.size)
end
end
如果Tag
有一个名为name
的属性,您可以像这样重构代码,以获得更好的性能和可读性:
class FilmTag < ActiveRecord::Base
# remove the .tags scope
end
class Film < ActiveRecord::Base
has_many :film_tags
has_many :tags, through: :film_tags
scope :with_all_tag_names, ->(tag_names) do
joins(film_tags: :tags)
.where(tags: { name: tag_names })
.group("films.id")
.having("count(tags.name) = ?", tag_names.size)
end
end