1

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

 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)})
       )
  }

其中context是一个 Array对象Tag

关键是这个范围产生以下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类上的各种范围。

谢谢你的帮助!

4

1 回答 1

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
 }
于 2012-08-10T17:26:52.247 回答