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.