Shafquat
Shafquat

Reputation: 103

Show pin/post average rating in index Ruby on Rails and Raty.js

I've used Ruby on Rails and Raty.js to create a rating system for my pins. You can see the average rating in the individual Show pages for each pin. I'd like to incorporate that into my index file. Currently, the rating that is showing for all pins in the index is the average rating of the first pin.

Note: I'm using Haml for the index file, but if you could provide an answer in basic html, that'll be fine.

index.html.haml:

.panel-footer
  .btn-group.pull-left
    %div{class: "srating", dscore: @avg_review }

:javascript
    $('.srating').raty({
        path: '/assets/',
        readOnly: true,
        score: function() {
            return $(this).attr('dscore');
        }
    });

pins_controller.rb:

class PinsController < ApplicationController
    before_action :find_pin, only: [:show, :edit, :update, :destroy, :upvote, :un_upvote]
    before_action :authenticate_user!, except: [:index, :show]

    def index
        @pins = Pin.all.order("created_at DESC").paginate(page: params[:page], per_page: 7)
        for singlepin in @pins
            @stars_reviews = StarsReview.where(pin_id: singlepin.id)

            if @stars_reviews.blank?
                @avg_review = 0
            else
                @avg_review = @stars_reviews.average(:rating).round(2)
            end
        end
    end

Upvotes: 0

Views: 282

Answers (1)

j-dexx
j-dexx

Reputation: 10416

It's actually showing the average rating for the last pin.

for singlepin in @pins
  @stars_reviews = StarsReview.where(pin_id: singlepin.id)

  if @stars_reviews.blank?
    @avg_review = 0
  else
    @avg_review = @stars_reviews.average(:rating).round(2)
  end
end

Each loop here is just setting the one variable to the new value.

So either add an average rating attribute on pin and update it everytime someone rates it.

Or make the variable an array:

@avg_reviews = []
for singlepin in @pins
  @stars_reviews = StarsReview.where(pin_id: singlepin.id)

  if @stars_reviews.blank?
    @avg_reviews << 0
  else
    @avg_reviews << @stars_reviews.average(:rating).round(2)
  end
end

Then output as you loop over the pins

<% @pins.each_with_index do |pin, i| %>
  %div{class: "srating", dscore: @avg_reviews[i] }
<% end %>

Or you could allow an attribute on pin that you set

class Pin
  attr_accessor :avg_review
end

for singlepin in @pins
  @stars_reviews = StarsReview.where(pin_id: singlepin.id)

  if @stars_reviews.blank?
    singlepin.avg_review = 0
  else
    singlepin.avg_review = @stars_reviews.average(:rating).round(2)
  end
end

Then access it in the view

<% @pins.each do |pin| %>
  %div{class: "srating", dscore: pin.avg_review }
<% end %>

Upvotes: 1

Related Questions