我有一个类似CMS的Rails 5应用,具有Story
和Tag
模型。故事has_and_belongs_to_many :tags
。我想创建一个范围,在其中可以传递多个标签,并获得包含传递给我的所有标签的所有故事。
例如:
story_1.tags # => [tag_a, tag_c]
story_2.tags # => [tag_b, tag_c]
story_3.tags # => [tag_a, tag_b, tag_c]
# Desired behavior
Story.with_tags([tag_a, tag_c]) # => [story_1, story_3]
Story.with_tags([tag_b, tag_c]) # => [story_2, story_3]
Story.with_tags([tag_a, tag_b]) # => [story_3]
我尝试制作单个with_tag
范围并将多个链接链接在一起,但是似乎进行了一个查询,尝试查找标记ID为1 AND 3(不返回任何内容)的单个联接记录。 / p>
def self.with_tag(tag)
joins(:tags).where(tags: { id: tag })
end
Story.with_tag(tag_a).with_tag(tag_c) # => []
我也尝试过将所有标签ID传递到联接表上的单个where子句中,但是随后我得到了具有任何标签的所有故事(更多的OR查询,我正在寻找AND)
def self.with_tags(tags)
joins(:stories_tags).where(stories_tags: { tag_id: tags }).distinct
end
Story.with_tags([tag_a, tag_c]) # => [story_1, story_2, story_3]
答案 0 :(得分:1)
您必须使用SQL HAVING
子句:
ids = [1,2,3]
Story.joins(:tags)
.where(:tags => { id: ids })
.group('stories.id')
.having('count(tags.id) >= ?', ids.size)
# ^^ if you want to get stories having exactly the tags
# provided, use equal instead