簡體   English   中英

Rails 3 ActiveRecord:按關聯計數排序

[英]Rails 3 ActiveRecord: Order by count on association

我有一個名為Song的模型。 我還有一個名為Listen的模型。 A 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 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

獎勵積分,添加測試:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM