[英]HTTP500: server error!! ActionView::Template::Error (undefined method `id' for nil:NilClass)
[英]Comment delete ActionView::Template::Error (undefined method `each' for nil:NilClass):
尝试删除评论时出现 500 错误。 在后端,评论被删除,但它会因 ActionView::Template::Error (undefined method `each' for nil:NilClass) 出错:即使应该填充 @comments。 我使用了 window.location.reload() 并且效果很好。 任何想法如何解决这个问题?
日志
Started DELETE "/api/comments/51" for ::1 at 2020-07-25 11:48:17 -0400
Processing by Api::CommentsController#destroy as JSON
Parameters: {"id"=>"51"}
Comment Load (0.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" = $1 LIMIT $2 [["id", 51], ["LIMIT", 1]]
↳ app/controllers/api/comments_controller.rb:38
(0.2ms) BEGIN
↳ app/controllers/api/comments_controller.rb:39
Comment Destroy (0.8ms) DELETE FROM "comments" WHERE "comments"."id" = $1 [["id", 51]]
↳ app/controllers/api/comments_controller.rb:39
(2.1ms) COMMIT
↳ app/controllers/api/comments_controller.rb:39
Rendering api/comments/index.json.jbuilder
Rendered api/comments/index.json.jbuilder (3.5ms)
Completed 500 Internal Server Error in 21ms (ActiveRecord: 3.7ms)
ActionView::Template::Error (undefined method `each' for nil:NilClass):
1:
2: @comments.each do |comment|
3: json.set! comment.id do
4: json.partial! 'comment', comment: comment
5: end
app/views/api/comments/index.json.jbuilder:2:in `_app_views_api_comments_index_json_jbuilder__2940510328301300636_70181083474860'
app/controllers/api/comments_controller.rb:40:in `destroy'
表示组件
import React from 'react';
class CommentIndex extends React.Component {
constructor(props) {
super(props)
this.handleDelete = this.handleDelete.bind(this);
}
componentDidMount() {
this.props.fetchComments();
}
componentDidUpdate(prev) {
if (Object.values(prev.comments).length !== Object.values(this.props.comments).length) {
this.props.fetchComments();
}
}
dateCreated(date) {
const dateCreated = new Date(date)
return dateCreated.toLocaleDateString();
}
authorInitial(id) {
const users = Object.values(this.props.state.entities.users);
const user = users.filter(user => user.id === id);
return user[0].username.split("")[0]
}
authorName(id) {
const users = Object.values(this.props.state.entities.users);
const user = users.filter(user => user.id === id);
return user[0].username
}
handleDelete(id) {
this.props.deleteComment(id)
// .then(window.location.reload())
}
render() {
const comments = Object.values(this.props.state.entities.comments);
const videoComments = comments.filter(comment => comment.video_id === this.props.id)
const commentNumber = function () {
if (videoComments.length === 1) {
return "1 Comment"
} else {
return `${videoComments.length} Comments`
}
}
const commentList = videoComments.map(comment => {
return (
<ul key={comment.id} >
<div className="comment-list-item">
<div id="left-side">
<h2 className="comment-author-initial">{this.authorInitial(comment.author_id)}</h2>
<div className="comment-body">
<div className="name-date">
<h2 className="comment-author-name">{this.authorName(comment.author_id)}</h2>
<h2 className="comment-upload-date"> commented on {this.dateCreated(comment.created_at)}</h2>
</div>
<h2 className="comment-text">{comment.body}</h2>
</div>
</div>
{/* {this.props.currentUser.id === comment.author_id ? <button id="delete-button"onClick={() => this.handleDelete(comment.id)}>Edit</button> : null} */}
{this.props.currentUser.id === comment.author_id ? <button id="delete-button"onClick={() => this.handleDelete(comment.id)}>Delete</button> : null}
</div>
</ul>
)
})
return (
<div id="comment-list">
<h1 className="comment-page-title">{commentNumber()}</h1>
<div className="comment-page-container">
<ul id="comment-ul">
<div id="comment-page-list">{commentList}</div>
</ul>
</div>
</div>
)
}
}
export default CommentIndex;
controller
class Api::CommentsController < ApplicationController
def index
@comments = Comment.all
render :index
end
def new
@comment = Comment.new
render :new
end
def show
@comment = Comment.find(params[:id])
render :show
end
def create
@comment = Comment.new(comment_params)
@comment.author_id = current_user.id
if @comment.save
render :show
else
render json: @comment.errors.full_messages , status: 422
end
end
def update
@comment = Comment.find(params[:id])
if @comment.update(comment_params)
render :show
else
render json: @comment.errors.full_messages, status: 422
end
end
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
render :index
end
def comment_params
params.require(:comment).permit(:body, :author_id, :video_id)
end
end
问题的原因是不言而喻的:
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
render :index
end
render:index
是非常规的。 您可能会成为一个非常常见的误解的受害者——render render:index
不会调用 controller 中的 index 方法。 它只是渲染视图。
在经典的 Rails 应用程序中,销毁资源通常会重定向到索引。
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
redirect_to :index, notice: 'Comment deleted.'
end
如果您正在创建一个为 JSON 服务的 controller,您通常会使用204 - No Content
响应代码进行响应:
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
head :no_content
end
但是您也可以用200 - OK
来响应,如果请求正文包含一个描述状态的实体,例如一些 JSON。
通过使用ActionController::MimeResponds你可以做到:
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
respond_to do |f|
f.html { redirect_to :index }
f.json { head :no_content }
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.