Rails 3 ActiveRecord:按关联计数

我有一个名为Song的模型。 我也有一个叫做Listen的模型。 一个Listen belongs_to :song ,一首歌:has_many listens (可以多次听)。

在我的模型中,我想定义一个self.top方法,它应该返回最多听的前5首歌曲。 我怎样才能实现使用has_many关系?

我正在使用Rails 3.1。

谢谢!

使用命名范围 :

 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 

更好的是,使用counter_cache会更快,因为你只会因为在你的查询中使用一个表

这是你的歌class:

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

那么,你的听课:

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

确保你添加了一个迁移:

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

奖励积分,添加testing:

 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 

或者,如果你想使用上面的方法,这里更简单一些,使用类方法而不是scope

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

对于rails 4.x,如果你的行没有任何联系很重要,

 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") }