2010-02-04 5 views
6

Esta es mi modelo:¿Cómo se puede obtener un recuento de filas de has_many: a través de las relaciones con: uniq => true

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 las relaciones están trabajando, pero tengo un requisito adicional que no puedo encontrar la solución para:

consideran esta relación en la clase de activos

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

llamando Asset.find (: en primer lugar) .tags devuelve una matriz de etiquetas como se esperaba, pero necesito para cada etiqueta que contiene una atributo de conteo que indica cuántas veces habría aparecido la fila si: uniq => verdadero no se hubiera especificado.

por ejemplo. más de un usuario podría aplicar la misma etiqueta a un activo. Me gustaría mostrar el nombre de la etiqueta más la cantidad de usuarios que la aplicaron.

Respuesta

5

Esto debería hacer exactamente lo que quiere.

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

En términos de filas devueltas: Grupo =>: Identificación del devolverá el mismo conjunto que: uniq => cierto, pero también le permitirá realizar los cálculos que desee. Esta afirmación requiere más mano de obra que: uniq => verdadero, por lo que le he asignado un nombre diferente que le permite elegir entre buscar las etiquetas únicas con sus recuentos agrupados o solo la lista de etiquetas únicas.

La instrucción anterior agregará el atributo de frecuencia a los registros devueltos. A través de la magia de method_missing, puedes acceder a eso con @ tag.frequency.

Uso:

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

imprimirá el ID, el nombre y número de ocurrencias de cada etiqueta para @asset.

+0

Agradable. ¡Mucha información buena allí! –

+0

No funciona del todo. Tuve que soltar el: joins =>: taggings y agregar un: source =>: tag. El siguiente funciona exactamente como se requiere: has_many: tags_with_count,: through =>: taggings,: source =>: tag,: group => "tags.id",: select => "tags. *, COUNT (\" taggings .id \ ") AS frequency" ..... No habría encontrado esto sin su ayuda. De todos modos, estoy aceptando su respuesta. Aunque sería bueno que pudieras editar tu respuesta. –

+0

Perdón por eso. Debería haber cogido las comillas anidadas, y necesito una opción de fuente. La solución ha sido editada para corregir esos pequeños errores. – EmFi

Cuestiones relacionadas