Как можно получить количество строк из has_many: через отношения с: uniq => true - PullRequest
6 голосов
/ 04 февраля 2010

Это моя модель:

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 возвращает массив тегов, как и ожидалось, но мне нужно, чтобы каждый тег содержал атрибут count, указывающий, сколько раз строка появилась бы, если:uniq => true не было указано.

например.более одного пользователя могут применять один и тот же тег к активу.Я хотел бы отобразить имя тега плюс количество пользователей, которые его применили.

1 Ответ

5 голосов
/ 04 февраля 2010

Это должно делать именно то, что вы хотите.

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.

...