Rails has_many error - Couldn't find ID

2019-07-24 13:45发布

问题:

I have a Comment and Reply. comment has_many replies

routes.rb

resources :comments do
  resources :replies
end

When I open comments/index and then select comments/show I print information about all the replies that are related to that comment.

<% @comment.replies.each do |reply| %>

I can also create another reply. All this works properly.

The problem comes when I decide to edit one of those replies.

<%=  link_to 'Edit', edit_comment_reply_path(@comment.replies,reply) %>

The strange thing is that if there is a comment with an ID the same as the ID of the reply that I want to modify, the edit is working properly. It is not even necessary the particular reply that I want to modify to belongs to that comment. But in case I want to edit reply with ID for example 66, but there is not a comment with id 66, I get an error:

Couldn't find Comment with 'id'=65
<%=form_with(model: @reply, url: [Comment.find(params[:id]), @reply]) do |form| %>

This is replies/_form.html.erb which apparently works as an edit form as well. In this case the reply.id is 65 and it is looking for a comment with the same ID which is not present.

回答1:

Did you try?

<%=  link_to 'Edit', edit_comment_reply_path(reply) %>


回答2:

What do your controllers look like? Also, you shouldn't be able to access replies that do not belong to your comment. Look at using proper scoping and authorization. I would guess the only reason it works is luck; because you do have a comment_id that matches the reply_id, the call does not fail.



回答3:

Ok, can you also post your comments controller. A few points: Make use of authorizations in your relevant functions (suggestion; assuming you're using policies)

def edit
  authorize @reply
end

If you plan on passing in the comment id, you should also set_comment (not just in create). That way you can also make sure the reply edit is not executed using a comment that does not belong to your user (or some other unwanted behaviours).

And also, you question talks about looking for Id 66, but the error mentions ID 65. Is that just a typo?



回答4:

In your RepliesController change the set comment method to

 def set_comment
    @comment = Comment.find(reply_params[:comment_id])
  end


回答5:

The problem lies in this line of code.

<%= link_to 'Edit', edit_comment_reply_path(@comment.replies,reply) %>

The edit_comment_reply_path method takes @comment as its first argument.

The correct code should be

<%=  link_to 'Edit', edit_comment_reply_path(@comment, reply) %>

Provided that you have assigned @comment in your controller edit action.

def edit
    @comment = Comment.find(params[:comment_id])
end

Or

before_action :set_comment, only: [:create, :edit]

The point is you must set the @comment in the correct action for the view.

The form_for is incorrect. You can passing in params[:id] which is the id of @reply.

<%= form_with(model: @reply, url: comment_reply_path(@comment, @reply)) do |form| %>