Como se pode obter uma contagem de fileiras de Has_Many: através das relações com: uniq => true

StackOverflow https://stackoverflow.com/questions/2199338

Pergunta

Este é o meu modelo:

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

Todas as relações estão funcionando, mas tenho um requisito adicional para o qual não consigo encontrar a solução:

Considere essa relação na classe de ativos

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

Chamar Asset.find (: primeiro) .Tags Retorna uma matriz de tags conforme o esperado, mas preciso que cada tag contenha um atributo de contagem indicando quantas vezes a linha teria aparecido se: uniq => true não fosse especificado.

por exemplo. Mais de um usuário pode aplicar a mesma tag a um ativo. Eu gostaria de exibir o nome da tag mais o número de usuários que o aplicaram.

Foi útil?

Solução

Isso deve fazer exatamente o que você deseja.

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

Em termos de linhas retornadas: grupo =>: O ID retornará o mesmo conjunto que: uniq => true, mas também permitirá que você execute os cálculos desejados. Essa declaração é mais trabalhosa do que: uniq => true, então eu dei um nome diferente, permitindo que você escolha se deseja buscar as tags exclusivas com suas contagens agrupadas ou apenas a lista de tags exclusivas.

A instrução acima adicionará o atributo de frequência aos registros retornados. Através da magia de Method_missing, você pode acessar isso com @tag.frequency.

Uso:

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

Imprimirá o ID, o nome e o número de ocorrências de cada tag para @asset.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top