【问题标题】:parent has all of children group in many to many relation父母在多对多关系中拥有所有孩子组
【发布时间】:2015-04-18 09:02:19
【问题描述】:

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

使用 Rails 4 我通过 film_tags 在 Film 和 Tag 之间建立了多对多关系。我想将电影范围限定为仅返回包含一组标签的电影。例如动作和喜剧都是标签,我想搜索具有这两个标签的电影。目前,我的系统意外地进行了“或”搜索,以便返回所有具有动作或喜剧的电影:

电影:

scope :includes_tags, ->(tags) {joins(:film_tag).merge(FilmTag.tags(tags))}

电影标签:

scope :tags, ->(tags) {where(['film_tags.tag_id IN (?)',tags.map(&:id)])}

是否可以通过这两个标签进行过滤,以便我可以在之后继续链接作用域?

【问题讨论】:

  • 你的joinfilm_tags (joins(:film_tags)) 的复数形式,不是吗?
  • 糟糕,它在我的代码中,只是这里的一个错字。
  • 你看我的回答了吗?有用吗?
  • 我目前正在实施它。感谢您的帮助。
  • 是的,这有效,谢谢。

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


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 2021-10-17
    相关资源
    最近更新 更多