ruby-on-railsrubypartial-viewsrating-systemhelpermethods

Helper Method does not work in my Index Page, Star Rating Sytem


I've implemented a Star Rating System using this tutorial http://eighty-b.tumblr.com/post/1569674815/creating-an-ajaxified-star-rating-system-in-rails-3

The Ajax works perfectly and so do my methods on the BOOKS SHOW PAGE

But for some reason, my Helper Methods do not work on the Index Page where I list multiple Books, therefore I am unable to call the current_user_rating on my Index Page.

it just doesn't show up, like on the show page it shows the integer or current user value, and on the index page. its just displays "N/A" even when it contains a value.

I have tried different things but can't seem to make it work...

Let me know if you need me to add anything else

New to rails please help :)

HELPERS

module BooksHelper 

##The first part of each Methods work on Show Page but Not Index

  def rating_ballot
    if @rating = current_user.ratings.find_by_book_id(params[:id])   ****
      @rating
    else
      current_user.ratings.new
    end
  end

  def current_user_rating
    if @rating = current_user.ratings.find_by_book_id(params[:id])   ****
     @rating.value
    else
      "N/A"
    end
  end

end

VIEWS

show.html (books)

<div id="book<%= @book.id %>">
   <div id="rating">
     <%= render :partial => 'ratings/rating', :locals =>{:book => @book} %>
   </div>
</div>

index.html.erb (books)

  <% @books.each do |book| %>
    <table id="book<%= book.id %>">
      <tbody>  
        <tr>  
          <td>
            <%= book.title %>
          </td> 
        </tr> 

        <tr>

          <td  id="rating">                   
            <%= render :partial => 'ratings/rating', :locals =>{:book => book} %>
          </td>

        </tr>
      <tbody>
    </table>
  <% end %>

_rating.html.erb (ratings)

 ###This Doesn't work in my INDEX PAGE :/

 Your Rating <%= current_user_rating %> 

 <%= form_for rating_ballot, :html => { :class => 'rating_ballot' }, :remote => true do |f| %>
   <%= render 'shared/error_messages', object: f.object %>

   <%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
   <%= radio_button_tag("rating[value]", 1, current_user_rating == 1, :class => 'rating_button') %>

   <%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
   <%= radio_button_tag("rating[value]", 2, current_user_rating == 2, :class => 'rating_button') %>

   <%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
   <%= radio_button_tag("rating[value]", 3, current_user_rating == 3, :class => 'rating_button') %>

   <%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
   <%= radio_button_tag("rating[value]", 4, current_user_rating == 4, :class => 'rating_button') %>

   <%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
   <%= radio_button_tag("rating[value]", 5, current_user_rating == 5, :class => 'rating_button') %>

   <%= hidden_field_tag("issue_id", issue.id) %>
   <%= f.submit :Submit, :style => "display:none" %>

 <% end %>

MODEL

class User < ActiveRecord::Base
  attr_accessible :name, :email, 

  has_many :ratings, dependent: :destroy
  has_many :rated_books, :through => :ratings, :source => :books

end

class Rating < ActiveRecord::Base
  attr_accessible :book_id, :user_id, :value

  belongs_to :user
  belongs_to :book

end

class Book < ActiveRecord::Base
  attr_accessible :description, :title

  has_many  :ratings
  has_many  :raters, :through => :ratings, :source => :users

end

CONTROLLER

class BooksController < ApplicationController

  respond_to :html, :js

  def show
    @book = Book.find(params[:id])
  end

  def index 
    @books = Book.all(:include => :ratings, :order => "book_number")
  end

end

Solution

  • When you go through show, you have this:

    @book = Book.find(params[:id])
    

    so presumably you have the params[:id] that your helper depends on. But why would you expect params[:id] to be anything other than nil when you get to your partial through index? You have accidentally coupled your helpers to your show controller by making bad assumptions about what is in params.

    My advice is to (almost) never access params in a helper method, you'll have clearer and more maintainable (let alone less buggy) code if you pass the helper as much information as possible through its arguments.

    Your helpers should look more like this:

    def rating_ballot(book_id)
      if @rating = current_user.ratings.find_by_book_id(book_id)
      #...
    
    def current_user_rating(book_id)
      if @rating = current_user.ratings.find_by_book_id(book_id)
      #...
    

    and then in your partial you can say:

    Your Rating <%= current_user_rating(book.id) %>
    

    I'd also recommend that you don't use @rating inside your helpers, that just pollutes your namespace with stray instance variables (that don't even have a clear connection to where they came from), just use a local rating variable instead.