복붙노트

[RUBY-ON-RAILS] 협회에 계산에 의해 주문 : 3 액티브 레일

RUBY-ON-RAILS

협회에 계산에 의해 주문 : 3 액티브 레일

나는 노래라는 이름의 모델이있다. 또한 모델이 들어 이름이 있습니다. has_many의 듣는다 (몇 번을들을 수 있습니다) : A는 belongs_to 듣기 : 노래와 노래.

내 모델에서 나는 5 곡이 가장 듣고 상단을 반환해야하는 방법의 self.top을 정의합니다. 어떻게 has_many 관계를 사용하여 해당을 달성 할 수있다?

나는 레일 3.1을 사용하고 있습니다.

감사!

해결법

  1. ==============================

    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
    
  2. ==============================

    2.더 나은 사용 counter_cache을 더 빠를 것이다 당신 때문에거야 만 쿼리에서 하나 개의 테이블을 사용하기 때문에

    더 나은 사용 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
    

    위의 방법 가고 싶은 경우 또는, 여기 조금 더 간단하게, 그리고 범위가 아닌 클래스 메소드를 사용하여

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

    3.레일은 연결 문제없이 당신의 행한다면, 시도 4.x의 경우 :

    레일은 연결 문제없이 당신의 행한다면, 시도 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")
      }
    
  4. from https://stackoverflow.com/questions/8696005/rails-3-activerecord-order-by-count-on-association by cc-by-sa and MIT license