itsource

레일 3 액티브 레코드:연관 개수별 주문

mycopycode 2022. 9. 25. 00:23
반응형

레일 3 액티브 레코드:연관 개수별 주문

저는 모델명을 가지고 있습니다.Song모델도 있어요.Listen.aListen 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

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

언급URL : https://stackoverflow.com/questions/8696005/rails-3-activerecord-order-by-count-on-association

반응형