多个连接与AND的条件

时间:2012-08-10 14:11:58

标签: sql ruby-on-rails

我有一个简单的项目标记系统,具有以下结构:

 class Item < ActiveRecord::Base
     has_many :taggings, :dependent => :destroy
     has_many :tags, :through => :taggings
 end

 class Tagging < ActiveRecord::Base
     belongs_to :tag
     belongs_to :item
 end

 class Tag < ActiveRecord::Base
     has_many :taggings, :dependent => :destroy
 end

我想在scope类中添加Item,以便能够获取具有给定标记集的所有项目(包括集合中的所有标记)

所以我尝试了以下范围:

 scope :tag_context, lambda { |context| (context.empty? ? all :
       joins(:taggings).where(:taggings => {tag_id => context.collect(&:id)})
       )
  }

其中contextArrayTag个对象。

关键是这个范围产生以下sql:

SELECT items.* FROM items INNER JOIN taggings ON taggings.item_id = items.id 
                          WHERE taggings.tag_id IN (1,2)

假设context包含标记1和2。

我想获得标记1和标记2标记的项目。 所以我假设,像:

SELECT items.* FROM items INNER JOIN taggings as t1 ON t1.item_id = items.id 
                          INNER JOIN taggings as t2 ON t2.item_id = items.id 
                          WHERE t1.tag_id = 1 AND t2.tag_id = 2

我应该如何在Rails范围内进行翻译? 我需要一个范围,以便能够链接Item类的各种范围。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您可以尝试动态构建范围(并且您不需要使用.empty?进行inject检查):

 scope :tag_context, lambda { |context| 
      context.collect(&:id).inject(self) do |m, id| 
        m.joins("INNER JOIN taggings as t#{id} ON t#{id}.item_id = items.id").
        where("t#{id}.tag_id = ?", id)
      end
 }