Comment peut-on obtenir un nombre de lignes de has_many: à travers les relations avec: uniq => true
-
25-09-2019 - |
Question
Ceci est mon modèle:
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
Toutes les relations travaillent mais j'ai une exigence supplémentaire que je ne peux pas trouver la solution pour:
considérer cette relation dans la classe d'actifs
has_many :tags, :through => :taggings, :uniq => true
appelant Asset.find (: en premier) .tags retourne un tableau de balises comme prévu mais j'ai besoin pour chaque balise pour contenir un attribut de comptage indiquant combien de fois la ligne serait apparu si: uniq => true n'a pas été spécifié.
par exemple. plus d'un utilisateur peut appliquer la même étiquette à un actif. Je voudrais afficher le nom de la balise ainsi que le nombre d'utilisateurs qui l'ont appliqué.
La solution
Cela devrait faire exactement ce que vous voulez.
has_many :tags_with_count, :source => :tag, :through => :taggings,
:group => "tags.id", :joins => :taggings,
:select = "tags.*, COUNT('taggings.id') AS frequency"
En termes de lignes retournées: groupe =>: id retourne le même ensemble que: uniq => vrai, mais il vous permettra également d'effectuer les calculs que vous voulez. Cette déclaration est plus de travail que:. Uniq => true, donc je lui ai donné un nom différent, vous permettant de choisir de récupérer les étiquettes uniques avec leurs comptes groupés, ou tout simplement la liste des balises uniques
La déclaration ci-dessus ajoutera l'attribut de fréquence aux enregistrements renvoyés. Grâce à la magie de method_missing, vous pouvez accéder à ce avec @ tag.frequency.
Utilisation:
@tags = @asset.tags_with_count
@tags.each{|tag| puts [tag.id, tag.name. tag.frequency].join "\t"}
imprimera le id, le nom et le nombre d'occurrences de chaque balise pour @asset.