查询Activerecord HABTM关系以包含数组的所有元素

我有一个ForumForumTag关系。 我还有一个名为@tags的变量数组。 此数组包含一些ForumTags的名称。 我希望能够查询并查找具有该数组所有值的所有论坛。 我目前有:

@forums = Forum.joines(:forum_tags).where(:forum_tags => {:name => @tags})。includes(:forum_tags).all

但是,这将返回arrays中至少具有一个值的所有论坛。

以下将要求论坛在@tags数组中包含所有论坛标记。 我假设一个forum不会多次拥有相同的forum_tag

 @forums = Forum.joins(:forum_tags).where(:forum_tags => {:name => @tags}).group("forums.id").having(['COUNT(*) = ?', @tags.length]).includes(:forum_tags).all 

这将生成如下SQL查询:

 @tags = ['foo', 'bar'] SELECT forums.id, forum_tags.id FROM forums LEFT OUTER JOIN forum_tags_forums on forum_tags_forums.forum_id = forums.id LEFT OUTER JOIN forum_tags ON forum_tags.id = forum_tags_forums.forum_tag_id WHERE forum_tags.name IN ('foo', 'bar') GROUP BY forums.id HAVING COUNT(*) = 2; 

这将通过与给定标记匹配的论坛对连接表中的所有行进行分组。 如果COUNT函数具有您要查找的标记总数的值(并且没有重复的forum / forum_tag对),则论坛必须包含所有标记。

要获得剩余的标签(评论中提出的问题):

 forum_tags = ForumTag.where(:name => @tags) @forums_with_leftovers = Forum.select("forums.*, GROUP_CONCAT(forum_tags.name) AS leftover_tags").joins(:forum_tags).where(['forums.id IN (?) AND NOT forum_tags.id IN (?)', @forums, forum_tags]).group("forums.id").all 

@forums_with_leftovers每个Forum对象都有一个额外的属性@forums_with_leftovers ,其中包含每个论坛对象中不包含在原始@tags变量中的逗号分隔的标记列表。