Come si può ottenere un conteggio delle righe da has_many: attraverso le relazioni con: uniq => true
-
25-09-2019 - |
Domanda
Questo è il mio modello:
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
Tutti i rapporti stanno lavorando, ma ho un requisito aggiuntivo che non riesco a trovare la soluzione per:
considerare questa relazione nella classe Asset
has_many :tags, :through => :taggings, :uniq => true
chiamando Asset.find (: in primo luogo) .tags restituisce un array di Tag, come previsto, ma ho bisogno per ogni Tag per contenere un attributo count che indica quante volte la fila sarebbe apparsa se: uniq => true non è stato specificato.
ad es. più di un utente potrebbe applicare lo stesso tag a una risorsa. Mi piacerebbe per visualizzare il nome del tag più il numero di utenti che hanno applicato esso.
Soluzione
Questo dovrebbe fare esattamente quello che vuoi.
has_many :tags_with_count, :source => :tag, :through => :taggings,
:group => "tags.id", :joins => :taggings,
:select = "tags.*, COUNT('taggings.id') AS frequency"
In termini di righe restituite: group =>: id restituirà lo stesso set di: uniq => vero, ma permetterà anche di eseguire i calcoli desiderati. Questa affermazione è più manodopera rispetto:. Uniq => vero, così ho dato un nome diverso che consente di scegliere se prelevare i tag univoci con i loro conteggi raggruppate, o semplicemente l'elenco dei tag univoci
La dichiarazione di cui sopra si aggiunge l'attributo di frequenza per i record restituiti. Attraverso la magia del method_missing, è possibile accedere a quella con @ tag.frequency.
Utilizzo:
@tags = @asset.tags_with_count
@tags.each{|tag| puts [tag.id, tag.name. tag.frequency].join "\t"}
stamperà l'id, il nome e il numero di occorrenze di ogni tag per @asset.