Rails 3 ActiveRecord: Ordina per conteggio sull’associazione

Ho un modello chiamato Song . Ho anche un modello chiamato Listen . A Listen belongs_to :song e una canzone :has_many listens (può essere ascoltata molte volte).

Nel mio modello voglio definire un metodo self.top che dovrebbe restituire le prime 5 canzoni ascoltate al massimo. Come posso ottenerlo usando la relazione has_many ?

Sto usando Rails 3.1.

Grazie!

Utilizzando gli ambiti nominati :

 class Song has_many :listens scope :top5, select("songs.id, OTHER_ATTRS_YOU_NEED, count(listens.id) AS listens_count"). joins(:listens). group("songs.id"). order("listens_count DESC"). limit(5) Song.top5 # top 5 most listened songs 

Ancora meglio, usa counter_cache che sarà più veloce perché dovrai solo utilizzare una tabella nella tua query

Ecco la tua lezione di canto:

 class Song < ActiveRecord::Base has_many :listens def self.top order('listens_count DESC').limit(5) end end 

Quindi, la tua lezione di ascolto:

 class Listen < ActiveRecord::Base belongs_to :song, counter_cache: true end 

Assicurati di aggiungere una migrazione:

 add_column :comments, :likes_count, :integer, default: 0 

Punti bonus, aggiungi test:

 describe '.top' do it 'shows most listened songs first' do song_one = create(:song) song_three = create(:song, listens_count: 3) song_two = create(:song, listens_count: 2) popular_songs = Song.top expect(popular_songs).to eq [song_three, song_two, song_one] end end 

Oppure, se vuoi seguire il metodo sopra, qui è un po 'più semplice, e usa un metodo di class piuttosto che un scope

 def self.top select('comments.*, COUNT(listens.id) AS listens_count'). joins(:listens). group('comments.id'). order('listens_count DESC'). limit(5) end 

Per rails 4.x prova questo se le tue file senza alcuna associazione contano:

 scope :order_by_my_association, lambda { select('comments.*, COUNT(listens.id) AS listens_total') .joins("LEFT OUTER JOIN listens ON listens.comment_id = comments.id") .group('comments.id') .order("listens_total DESC") }