I have an index page of art that I vote on with ratings model. I can vote on the show page but I want it to be able to vote on the index page also. The form for the ratings has three variables. How should the Art Controller index page look and the code for the index html page. I'm getting an error that "rating" is undefined. Please help, this is like the last hurdle I got to get over to complete this project.
**Update: I changed my routes so the form only has two variables now. But still having trouble rendering the form on the index page.
Routes to a new rating
new_art_rating GET /arts/:art_id/ratings/new(.:format)
Routes.rb
resources :campaigns do
resources :lyrics do
member do
get "like", to: "lyrics#upvote"
get "dislike", to: "lyrics#downvote"
end
resources :comments
end
resources :arts do
member do
get "like", to: "arts#upvote"
get "dislike", to: "arts#downvote"
end
resources :commentarts
end
end
resources :arts do
resources :ratings
end
Art Index
<% @arts.each do |art| %>
<div class="container-md">
<%= render partial: 'ratings/form', :locals =>{:campaign => @campaign, :art => @art, :rating => @art.rating} %>
<%= link_to campaign_art_path(@campaign, art) do %>
<%= image_tag art.image.url(:small) %>
<% end %>
Arts Controller
class ArtsController < ApplicationController
before_action :tag_cloud, :only => [:index]
load_and_authorize_resource :only => [:show, :edit, :update, :destroy]
before_action :find_post, only: [:show, :edit, :update, :destroy, :upvote, :downvote]
before_action :set_campaign
before_action :authenticate_user!, except: [:index, :show]
impressionist :actions=>[:show,:index], :unique => [:impressionable_type, :impressionable_id, :session_hash]
def index
@arts = Art.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 10)
@rating = Rating.new
end
def show
@commentarts = Commentart.where(art_id: @art)
@ratings = Rating.where(art_id: @art)
@random_art = Art.where.not(id: @art).order("RANDOM()").first
end
def new
@art = Art.new
end
def create
@art = Art.new(post_params)
@art.user_id = current_user.id
@art.campaign_id = @campaign.id
if @art.save
redirect_to([@art.campaign, @art])
else
render 'new'
end
end
def edit
end
def update
if @art.update(post_params)
redirect_to([@art.campaign, @art])
else
render 'edit'
end
end
def destroy
@art.destroy
redirect_to root_path
end
def upvote
@art.upvote_by current_user
redirect_to([@art.campaign, @art])
end
def downvote
@art.downvote_by current_user
redirect_to([@art.campaign, @art])
end
def tagged
if params[:tag].present?
@arts = Art.tagged_with(params[:tag]).order("created_at desc")
else
@arts = Art.all.order("created_at desc")
end
end
def tag_cloud
@tags = Art.tag_counts_on(:tags)
end
private
def find_post
@art = Art.find(params[:id])
end
def set_campaign
@campaign = Campaign.find(params[:campaign_id])
end
def post_params
params.require(:art).permit( :image, :description, :artist, :typeart, :link)
end
end
Ratings Controller
class RatingsController < ApplicationController
before_action :authenticate_user!
def create
@art = Art.find(params[:art_id])
@rating = Rating.create(params[:rating].permit(:rate))
@rating.user_id = current_user.id
@rating.art_id = @art.id
if @rating.save
redirect_to([@art.campaign, @art])
else
render 'new'
end
end
end
Form view
<%= simple_form_for([@art, @art.ratings.build]) do |f| %>
<%= f.error_notification %>
<div class="field">
<div id="star-rating"></div>
</div>
<%= f.button :submit, "Rate", class: "button" %>
<% end %>
<script>
$('#star-rating').raty({
path: '/assets/',
scoreName: 'rating[rate]'
});
</script>
Campaign Controller
class CampaignsController < ApplicationController
before_action :find_campaign, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
has_scope :free
has_scope :open
has_scope :closed
def index
@campaigns = Campaign.all.order("created_at DESC")
@free_campaign = Campaign.free.first
@open_campaigns = Campaign.open.all
@closed_campaigns = Campaign.closed.all
end
def show
@lyrics = Lyric.where(campaign_id: @campaign.id).order("created_at DESC")
@arts = Art.where(campaign_id: @campaign.id).order("created_at DESC")
@time = Time.now
end
def new
@campaign = current_user.campaigns.build
end
def create
@campaign = current_user.campaigns.build(campaign_params)
if @campaign.save
redirect_to @campaign
else
render 'new'
end
end
def edit
end
def update
if @campaign.update(campaign_params)
redirect_to @campaign
else
render 'edit'
end
end
def destroy
@campaign.destroy
redirect_to root_path
end
private
def find_campaign
@campaign = Campaign.find(params[:id])
end
def campaign_params
params.require(:campaign).permit(:title, :description, :timer, :timer2, :image, :status)
end
end
Error Message is in the Arts#index. Undefined method ratings. First line in my form.
NoMethodError in Arts#index undefined method `ratings' for nil:NilClass
Extracted source (around line #1):
**<%= simple_form_for([@art, @art.ratings.build]) do |f| %>**
<%= f.error_notification %>
<div class="field">
<div id="star-rating"></div>
Presumably Arts index has multiple Art instances, so there is not '@art'.
Etc. Or if there really is only one Art displayed on index, then instantiate that in the controller.
Perhaps also edit this line? I need to see the error log to see where you're seeing the error.
I'd break that out into a separate method:
And I'd check what the javascript 'raty' library is actually inserting into the DOM and whether it really is sending the params you think it is?