父母对所有儿童群体都有多对多的关系

时间:2015-02-17 15:47:36

标签: mysql ruby-on-rails-4 join has-many-through

我不能确定正确的术语,所以我无法找到任何帮助。

使用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)])}

是否可以通过这两种标签进行过滤,以便我可以继续链接范围?

1 个答案:

答案 0 :(得分:1)

您可以使用grouphaving语句来构建这样的范围(未经测试):

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