Trying to add a partial form to my index page. How

2019-08-06 19:26发布

问题:

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>

回答1:

Presumably Arts index has multiple Art instances, so there is not '@art'.

<% @arts.each do |art| %>
  <%= simple_form_for([art, art.ratings.build]) do |f| %>

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.

Rating.create(params[:rating].permit(:rate))

I'd break that out into a separate method:

Rating.create(rating_params[:rate))

def rating_params
  params.require(:rating).permit(:rate)
end

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?