Reputation: 2921
I have two models at play here, a Tab, and a Rating.
A Tab
has_many
Ratings
, and each Rating
belongs_to
one Tab
; each Rating
has a value
between 1 and 5.
Here are my models, with the relevant code:
tab.rb
class Tab < ApplicationRecord
...
has_many :ratings, dependent: :destroy
...
end
rating.rb
class Rating < ApplicationRecord
...
belongs_to :tab
...
end
And this is how my index view is displayed:
with the Rating
column being the average rating value of the tab.
Right now, to get each tab's average rating, I'm executing a query for each tab's average rating. This is very slow, and I am looking to improve this.
Here's my controller, with the relevant method as it is:
tabs_controller.rb
class TabsController < ApplicationController
...
def index
# need to display average rating
# don't want to do one query for each tab
# so, make index return a table that includes avg rating as a column
@tabs = Tab.all
end
...
end
These are all the queries generated when I load the tab index
page:
I think that I will need to execute a query in the index
controller method that returns a table including all the tabs, and the average rating of each of those tabs. How would I do this?
I might also need to use a view. If anyone could lead me in the right direction, that would be very appreciated.
Upvotes: 3
Views: 640
Reputation: 340
I have used jQuery Raty before here.
To compute average rating in your TabsController show action you can add this
...
@ratings = Rating.where(tab_id: @tab.id)
if @tab.ratings.any?
@avg_rating=@tabs.average(:value).round(2)
else
@avg_rating=0
end
...
and to display it in show page
<div class="start-rating" data-score= <%= @avg_rating %> ></div>
but in the index page, do this
<div class="start-rating" data-score= <%= tab.ratings.average(:value) %> > </div>
Upvotes: 0
Reputation: 1431
Try using this. this will work
Tab.joins(:ratings).select("tabs.*, AVG(ratings.value) AS average_ratings").group("tab.id")
Upvotes: 3