¿Cómo se puede obtener un recuento de filas de has_many: a través de las relaciones con: uniq => true
-
25-09-2019 - |
Pregunta
Esta es mi 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 las relaciones están trabajando pero tiene un requisito adicional que no puedo encontrar la solución para:
en cuenta 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 para contener un atributo de recuento que indica cuántas veces habría aparecido la fila si: uniq => cierto no se especificó.
por ejemplo. más de un usuario podría aplicar la misma etiqueta a un Activo. Me gustaría mostrar la etiqueta con su nombre más el número de usuarios que se aplicaban a él.
Solución
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 declaración es más mano de obra que:. Uniq => verdadero, así que le he dado un nombre diferente que le permite elegir si desea recuperar las etiquetas únicas con sus recuentos agrupados, o simplemente la lista de etiquetas únicas
La declaración anterior se sumará el atributo de frecuencia de los registros devueltos. A través de la magia de method_missing, puede acceder a que 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.