Rails ERB 验证
Rails ERB Validation
我正在尝试向我的 Rails 应用添加验证,以便在用户访问错误 ID 时显示错误消息。该项目有评论,如果我去 http://localhost:3000/reviews/:id that doesn't exist
应用程序崩溃,我想通过显示消息来防止运行时错误。
在模型中,我得到了这个验证:
class Review < ApplicationRecord
validates :id, presence: true
end
然后,在 reviews/show.html.erb
文件中,我尝试这样做:
<% if @review.valid? %>
<div class='review-header'>
....
</div>
<% else %>
<% @review.errors.objects.first.full_message %>
<% end %>
这也是评论管理员:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :authorize!, only: [:edit, :destroy]
def index
if params[:search]
@reviews = Review.where("title like ?", "%#{params[:search]}%")
else
@reviews = Review.all
end
end
def new
@review = Review.new
@comment = Comment.new
@comment.review_id = @review.id
#We need to declare the comments in the new action.
end
def create
@review = current_user.reviews.new(review_params)
if @review.save
redirect_to review_path(@review)
else
render 'new'
end
end
def show
@comment = Comment.new
#We also need to declare the new comment in the show action.
end
def edit
end
def update
if @review.update(review_params)
redirect_to review_path(@review)
else
render 'edit'
end
end
def destroy
@review.destroy
redirect_to reviews_path
end
private
def set_review
@review = Review.find_by(id: params[:id])
end
def review_params
params.require(:review).permit(:title, :content, :category_id, :search)
end
def authorize!
authorize @review #authorize method using the Pundit gem
end
end
但是,我的项目一直在崩溃而不是显示消息。如果有什么办法可以使这项工作?谢谢。
问题是,如果 ID 与数据库中的评论不对应,@review
对象将是 nil
,您的行 if @review.valid?
将抛出错误。
你需要一个不同的测试,比如
<% if @review.present? %>
<div class='review-header'>
....
</div>
<% else %>
Review does not exist.
<% end %>
问题的整个设置实际上是错误的。
您不需要为 ID 添加模型验证,因为 ID 是在您插入记录时由数据库自动生成的。在大多数数据库中,主键也是 non-nullable。添加验证实际上会破坏模型,因为这会阻止您在不手动分配 id 的情况下保存记录(坏主意)。
验证控制器中是否可以找到记录也不是模型的工作。相反,您的控制器应该使用 find
以便在找不到记录时尽早退出:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :authorize!, only: [:edit, :destroy]
private
def set_review
@review = Review.find(params[:id])
end
end
这将停止执行方法和其他回调,并防止 NoMethodError
s 必然发生。如果应该 CRUD 的记录不存在,则继续处理请求是没有意义的。
默认情况下,Rails 将通过呈现位于 public/404.html
的静态 HTML 页面并返回 404 状态代码来处理未捕获的 ActiveRecord::RecordNotFound
异常。如果你想在控制器级别自定义它,请使用 rescue_from
:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :authorize!, only: [:edit, :destroy]
rescue_from ActiveRecord::RecordNotFound, with: :not_found
private
def set_review
@review = Review.find(params[:id])
end
def not_found
# renders app/reviews/not_found.html.erb
render :not_found,
status: :not_found
end
end
请注意,这应该在不同的视图中完成。如果您将 <% if @review.present? %>
添加到 reviews/show.html.erb
视图,您的 Rails 许可证应该被吊销,因为视图 唯一的工作 是显示评论.
您还可以使用 config.exceptions_app
在应用程序级别配置响应。
我正在尝试向我的 Rails 应用添加验证,以便在用户访问错误 ID 时显示错误消息。该项目有评论,如果我去 http://localhost:3000/reviews/:id that doesn't exist
应用程序崩溃,我想通过显示消息来防止运行时错误。
在模型中,我得到了这个验证:
class Review < ApplicationRecord
validates :id, presence: true
end
然后,在 reviews/show.html.erb
文件中,我尝试这样做:
<% if @review.valid? %>
<div class='review-header'>
....
</div>
<% else %>
<% @review.errors.objects.first.full_message %>
<% end %>
这也是评论管理员:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :authorize!, only: [:edit, :destroy]
def index
if params[:search]
@reviews = Review.where("title like ?", "%#{params[:search]}%")
else
@reviews = Review.all
end
end
def new
@review = Review.new
@comment = Comment.new
@comment.review_id = @review.id
#We need to declare the comments in the new action.
end
def create
@review = current_user.reviews.new(review_params)
if @review.save
redirect_to review_path(@review)
else
render 'new'
end
end
def show
@comment = Comment.new
#We also need to declare the new comment in the show action.
end
def edit
end
def update
if @review.update(review_params)
redirect_to review_path(@review)
else
render 'edit'
end
end
def destroy
@review.destroy
redirect_to reviews_path
end
private
def set_review
@review = Review.find_by(id: params[:id])
end
def review_params
params.require(:review).permit(:title, :content, :category_id, :search)
end
def authorize!
authorize @review #authorize method using the Pundit gem
end
end
但是,我的项目一直在崩溃而不是显示消息。如果有什么办法可以使这项工作?谢谢。
问题是,如果 ID 与数据库中的评论不对应,@review
对象将是 nil
,您的行 if @review.valid?
将抛出错误。
你需要一个不同的测试,比如
<% if @review.present? %>
<div class='review-header'>
....
</div>
<% else %>
Review does not exist.
<% end %>
问题的整个设置实际上是错误的。
您不需要为 ID 添加模型验证,因为 ID 是在您插入记录时由数据库自动生成的。在大多数数据库中,主键也是 non-nullable。添加验证实际上会破坏模型,因为这会阻止您在不手动分配 id 的情况下保存记录(坏主意)。
验证控制器中是否可以找到记录也不是模型的工作。相反,您的控制器应该使用 find
以便在找不到记录时尽早退出:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :authorize!, only: [:edit, :destroy]
private
def set_review
@review = Review.find(params[:id])
end
end
这将停止执行方法和其他回调,并防止 NoMethodError
s 必然发生。如果应该 CRUD 的记录不存在,则继续处理请求是没有意义的。
默认情况下,Rails 将通过呈现位于 public/404.html
的静态 HTML 页面并返回 404 状态代码来处理未捕获的 ActiveRecord::RecordNotFound
异常。如果你想在控制器级别自定义它,请使用 rescue_from
:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :authorize!, only: [:edit, :destroy]
rescue_from ActiveRecord::RecordNotFound, with: :not_found
private
def set_review
@review = Review.find(params[:id])
end
def not_found
# renders app/reviews/not_found.html.erb
render :not_found,
status: :not_found
end
end
请注意,这应该在不同的视图中完成。如果您将 <% if @review.present? %>
添加到 reviews/show.html.erb
视图,您的 Rails 许可证应该被吊销,因为视图 唯一的工作 是显示评论.
您还可以使用 config.exceptions_app
在应用程序级别配置响应。