Question

I'm setting up a simple ruby/rails app where users can review albums. On an album's show page I average all the user reviews associated with that album through this code in my albums controller

def show
  @album = Album.find_by_id(params[:id])
  if @album.reviews.present?
    @ratings = Review.where(album_id: @album).average(:rating).truncate(2)
  else
    render 'show'
  end
end

This gives me an average rating for each album. On my home page (routed through a different controller) I want to display the top 7 albums with the highest average rating.

What I originally did was put this code into the separate home page controller:

@albums = Album.all
@ratings = @albums.each {|album| album.reviews.average(:rating).to_f}
@ranked_ratings =  @ratings.sort_by {|rating| rating}
@top_seven = @ranked_ratings.reverse[0...7]

I thought I found the solution until I realized all I'm showing is the last 7 albums entered into the database.

Going back to the drawing board I have been able to get an array of all the albums (each element within the array is a list of reviews associated with that album) with this code in my controller:

@albums = Album.all
@ratings = @albums.collect {|album| album.reviews}

I'm stuck at this point trying to figure out how to cycle through @ratings and find the average rating for each album_id, then order those records by the highest average rating and display them in a view.

Was it helpful?

Solution

try @albums = Album.joins(:reviews).select("album.id, avg(reviews.rating) as average_rating).group("album.id").order("average_rating DESC")

I extrapolated it from: Ruby on Rails: Order users based on average ratings with most reviews?

Update:

try this instead: @albums = Album.joins(:reviews).select("*, avg(reviews.rating) as average_rating").group("albums.id").order("average_rating DESC")

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top