Reputation: 793
I'm trying to display average ratings for jobs on my index page, it works perfectly fine on my show page
but on my index page the stars are there but are blank, how do i get them to display on my index page?
My Show Page:
<h4>Average Rating</h4>
<div class="average-review-rating" data-score=<%= @average_review %>></div>
<span class="number-of-reviews">Based on <%= @job.reviews.count %> reviews</span>
</div>
</div>
<script>
$('.review-rating').raty({
readOnly: true,
score: function() {
return $(this).attr('data-score');
},
path: '/assets/'
});
</script>
<script>
$('.average-review-rating').raty({
readOnly: true,
path: '/assets/',
score: function() {
return $(this).attr('data-score')
}
});
</script>
Jobs Show controller
def show
if @job.reviews.blank?
@average_review = 0
else
@average_review = @job.reviews.average(:rating).round(2)
end
end
My Index Page:
<% @jobs.each do |job| %>
<%= link_to job.title, job_path(job) %></h4>
<%= job.category %></p>
<%= job.city %>
<div class="average-review-rating" data-score=<%= average_review %>></div>
<span class="number-of-reviews">Based on <%= job.reviews.count %> reviews</span>
</div>
</div>
<% end %>
<script>
$('.average-review-rating').raty({
readOnly: true,
path: '/assets/',
score: function() {
return $(this).attr('data-score')
}
});
</script>
Upvotes: 1
Views: 532
Reputation: 21130
You can fetch these results like so:
def index
@jobs = Job.all
@average_reviews = Review.where(job_id: @jobs)
.group(:job_id)
.average(:rating)
.transform_values { |rating| rating.round(2) }
end
This will return a hash with job ids as keys and the average rating as value (rounded to 2 decimals). To access these average ratings you can do the following in your index view:
@jobs.each do |job|
average_review = @average_reviews[job.id]
end
The above code only makes 2 SQL calls, 1 for fetching your jobs and 1 for fetching all average reviews for all the fetched jobs. Keep in mind that if a job has no reviews. When fetching the average rating from the hash the value nil
is returned.
Upvotes: 0
Reputation: 6455
In your show page, you have @average_review defined. I'm guessing this was done in your jobs controller in the show action.
In your index page, you will need to calculate the average rating for each job as you are iterating through them. You can do this the same way you defined @average_rating. If you are defining your @average_rating in the show action as:
@average_rating = job.reviews.sum('score') / job.reviews.count
You will need to either define this method in the model (the better option), so something like:
app/models/job.rb
def average_review
reviews.sum('score') / reviews.count
end
Then in your index page:
<div class="average-review-rating" data-score=<%= job.average_review %>></div>
The other option is to set a variable for each object on the index page itself, less work but probably not as neat:
<% @jobs.each do |job| %>
<%= link_to job.title, job_path(job) %></h4>
<%= job.category %></p>
<%= job.city %>
<% average_review = job.reviews.sum('score') / job.reviews.count %>
<div class="average-review-rating" data-score=<%= average_review %>></div>
<span class="number-of-reviews">Based on <%= job.reviews.count %> reviews</span>
</div>
</div>
<% end %>
EDIT:
In your app/models/job.rb
def average_review
reviews.blank? ? 0 : reviews.average(:rating).round(2)
end
And index.html.erb
<div class="average-review-rating" data-score=<%= job.average_review %>></div>
Upvotes: 1