Chr*_*jer 59 mysql activerecord ruby-on-rails ruby-on-rails-3
我有一个名为的模型Song.我也有一个名为的模型Listen.A Listen belongs_to :song,和一首歌:has_many listens(可以多次收听).
在我的模型中,我想定义一个方法self.top,该方法应该返回最多听过的前5首歌曲.如何使用这种has_many关系实现这一目标?
我正在使用Rails 3.1.
谢谢!
cly*_*yfe 93
使用命名范围:
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
Run Code Online (Sandbox Code Playgroud)
Nea*_*eal 32
更好的是,使用counter_cache哪个会更快,因为你只会因为在查询中使用一个表
这是你的歌曲课程:
class Song < ActiveRecord::Base
has_many :listens
def self.top
order('listens_count DESC').limit(5)
end
end
Run Code Online (Sandbox Code Playgroud)
然后,你的听课:
class Listen < ActiveRecord::Base
belongs_to :song, counter_cache: true
end
Run Code Online (Sandbox Code Playgroud)
确保添加迁移:
add_column :comments, :likes_count, :integer, default: 0
Run Code Online (Sandbox Code Playgroud)
奖励积分,添加测试:
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
Run Code Online (Sandbox Code Playgroud)
或者,如果你想使用上面的方法,这里更简单,并使用类方法而不是 scope
def self.top
select('comments.*, COUNT(listens.id) AS listens_count').
joins(:listens).
group('comments.id').
order('listens_count DESC').
limit(5)
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29212 次 |
| 最近记录: |