简体   繁体   中英

Ruby on Rails - Create polymorphic comment through partial

I'm currently trying to implement polymorphic comments within my app, but I'm running into problems with converting my partial form.

I was following this tutorial, step-by-step-guide-to-polymorphic-associations-in-rails , but it didn't go over this section.

Mainly, I have an Image that is commentable, and a partial at the bottom to allow users to comment on the Image.

However, when submitting the form, it can't find the @commentable object as params[:id] and params[:image_id] are both nil.

I'm having problems understanding how I'm supposed to pass this information, as the partial knows this information, but the controller does not.

// images/show.html.erb

<div class="container comment-form" >
    <%= render 'comments/form', comment: @image.comments.build  %>
</div>

// comments/_form.html.erb

<%= bootstrap_form_for(comment) do |f| %>
  <%= f.text_area :message, :hide_label => true, :placeholder => 'Add a comment' %>
  <%= f.submit 'Reply', :class=> 'btn btn-default pull-right' %>
<% end %>

// comments_controller.rb

def create       
    @commentable = find_commentable
    @comment = @commentable.comments.build(comment_params) <<<<<

    respond_to do |format|
      if @comment.save
        format.html { redirect_to (comment_path @comment), notice: 'Comment was successfully created.' }
        format.json { render :show, status: :created, location: @comment }
      else
        format.html { render :new }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

Error on @comment = @commentable.comments.build(comment_params)

undefined method comments' for nil:NilClass`

I also noticed that there is no id in the request parameters.

Parameters:

{"utf8"=>"✓", "authenticity_token"=>"xxxxxx", "comment"=>{"message"=>"nice photo"}, "commit"=>"Reply"}

Thanks for your help.

When you pass a record to a form builder rails uses the polymorphic route helpers * to lookup the url for the action attribute.

To route to a nested resource you need to pass the parent and child(ren) in an array:

bootstrap_form_for([@commentable, @comment])
# or
bootstrap_form_for([@comment.commentable, @comment])

This would give the path /images/:image_id/comments for a new record and /images/:image_id/comments/:id if it has been persisted.

You are attempting to build your comment twice. Once in the show.html, with comment: @image.comments.build and then again in your create method with @comment = @commentable.comments.build(comment_params) <<<<<

The tutorial you linked to included the private method below. If your goal is to create a comment that belongs to your Image object, the method below would look for a param with your image_id , and would return Image.find(params[:image_id])

def find_commentable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      return $1.classify.constantize.find(value)
    end
  end
  nil
end

You could change your show.html to pass in your image_id as a hidden param with:

<div class="container comment-form" >
  <%= render 'comments/form', image_id: @image.id  %>
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM