59 votes

Rails 3 ActiveRecord: à l'ordre par le comte de l'association

J'ai un modèle du nom de la Chanson. J'ai aussi un modèle nommé Écouter. Pour écouter appartient à une chanson et une chanson ont beaucoup d'écoute (peut-être écouter de nombreuses fois).

Dans mon modèle, je veux définir une méthode d'auto.haut, qui devrait récupérer le top 5 des chansons de commande par le nombre de fois qu'il a été écouté.

Je suis à l'aide de Rails 3.1.

Merci!

95voto

clyfe Points 15388

En utilisant nommé étendues:

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

33voto

Neal Points 1594

Mieux encore, utiliser counter_cache qui sera plus rapide parce que vous aurez seulement parce que l'utilisation d'une table dans votre requête

Ici est votre chanson de la classe:

class Song < ActiveRecord::Base
  has_many :listens

  def self.top
    order('listens_count DESC').limit(5)
  end
end

Alors, à votre écoute classe:

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

Assurez-vous d'ajouter une migration:

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

Les points de Bonus, ajouter le test:

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

Ou, si vous voulez aller avec la méthode ci-dessus, ici c'est un peu plus simplement, et à l'aide d'une méthode de classe plutôt que d' scope

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X