6

这是我的模型:

class Tag < ActiveRecord::Base
  # id, name
  has_many :taggings
end

class Tagging < ActiveRecord::Base
  # id, tag_id, owner_id, target_type, target_id
  belongs_to :tag
  belongs_to :owner, :class_name => 'User'
  belongs_to :target, :polymorphic => true
  validates_uniqueness_of :tag_id, :scope => [ :target_id, :target_type, :owner_id ]
end

class Asset < ActiveRecord::Base
  # id, owner_id, title, type, etc
  belongs_to :owner, :class_name => 'User'
  has_many :taggings, :as => :target
  has_many :taggers, :through => :taggings, :source => :owner, :uniq => true
  has_many :tags, :through => :taggings, :uniq => true
end

class User < ActiveRecord::Base
  # id, name, email, etc
  has_many :assets, :foreign_key => 'owner_id'
  has_many :my_taggings, :class_name => 'Tagging', :foreign_key => 'owner_id'
  has_many :my_tags, :through => :my_taggings, :source => :tag, :uniq => true
  has_many :taggings, :as => :target
  has_many :taggers, :through => :taggings, :source => :owner, :uniq => true
  has_many :tags, :through => :taggings, :uniq => true
end

所有的关系都有效,但我有一个额外的要求,我找不到解决方案:

在资产类别中考虑这种关系

has_many :tags, :through => :taggings, :uniq => true

调用 Asset.find( :first ).tags 按预期返回一个标签数组,但我需要每个标签包含一个计数属性,指示如果未指定 :uniq => true 则该行将出现多少次。

例如。多个用户可以将相同的标签应用于资产。我想显示标签名称以及应用它的用户数量。

4

1 回答 1

5

这应该完全符合您的要求。

has_many :tags_with_count, :source => :tag, :through => :taggings, 
  :group => "tags.id", :joins => :taggings,
  :select = "tags.*, COUNT('taggings.id') AS frequency"

就返回的行而言 :group => :id 将返回与 :uniq => true 相同的集合,但它也允许您执行所需的计算。这个语句比 :uniq => true 更费力,所以我给它起了一个不同的名字,让你可以选择是获取具有分组计数的唯一标签,还是只获取唯一标签列表。

上面的语句会将频率属性添加到返回的记录中。通过method_missing 的魔力,您可以使用@tag.frequency 访问它。

用法:

@tags = @asset.tags_with_count
@tags.each{|tag| puts [tag.id, tag.name. tag.frequency].join "\t"}

将为@asset 打印每个标签的ID、名称和出现次数。

于 2010-02-04T16:17:50.627 回答