Rails ERB 验证
我正在尝试向我的 Rails 应用程序添加验证,以便在用户访问错误的 id 时显示错误消息。该项目有评论,如果我转到不存在的 http://localhost:3000/reviews/:id
应用程序崩溃,我想通过显示一条消息来防止运行时错误。
在模型中,我得到了这个验证:
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
但是,我的项目不断崩溃而不是显示一条消息。如果有什么办法可以让我完成这项工作吗?谢谢。
I'm trying to add a validation to my Rails app in order to display an error message if the user goes to the wrong id. The project has reviews, if I go to http://localhost:3000/reviews/:id that doesn't exist
the app crashes, I'd like to prevent the runtime error by displaying a message.
In the model, I got this validation:
class Review < ApplicationRecord
validates :id, presence: true
end
Then, in the reviews/show.html.erb
file, I'm trying this:
<% if @review.valid? %>
<div class='review-header'>
....
</div>
<% else %>
<% @review.errors.objects.first.full_message %>
<% end %>
This is also the Reviews Controller:
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
However, my project keep crashing rather than showing a message. If there's any way I can make this work? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这个问题的整个设置实际上被打破了。
您不需要为 id 添加模型验证,因为 id 是在您插入记录时由数据库自动生成的。在大多数数据库上,主键也是不可为空的。添加验证实际上会破坏模型,因为这会阻止您在不手动分配 ID 的情况下保存记录(坏主意)。
验证是否可以在控制器中找到记录也不是模型的工作。相反,您的控制器应该使用
find
,以便在找不到记录时尽早退出:这会停止方法和其他回调的执行,并防止绑定到的
NoMethodError
发生。如果应该进行 CRUD 的记录不存在,则继续处理请求是没有意义的。默认情况下,Rails 将通过呈现位于
public/404.html
的静态 HTML 页面并返回 404 状态代码来处理未捕获的ActiveRecord::RecordNotFound
异常。如果您想在控制器级别自定义此操作,请使用rescue_from
:请注意,这应该在不同的视图中完成。如果添加
<% if @review.present? %>
到您的reviews/show.html.erb
视图,您应该吊销您的 Rails 许可证,因为视图唯一的工作就是显示评论。您还可以使用 config.exceptions_app 在应用程序级别配置响应。
The whole setup of the question is actually broken.
You don't need to add a model validation for the id since ids are automatically generated by the database when you insert records. On most databases primary keys are also non-nullable. Adding the validation will actually break the model as will prevent you from saving records without manually assigning an id (bad idea).
Its also not the models job to verify that a record can be found in the controller. Instead your controller should use
find
so that it bails early if the record cannot be found:This halts execution of the method and other callbacks and prevents the
NoMethodError
s that are bound to occur. There is no sense in continuing to process a request if the record that its supposed to CRUD doesn't exist.By default Rails will handle an uncaught
ActiveRecord::RecordNotFound
exception by rendering a static HTML page located atpublic/404.html
and returning a 404 status code. If you want to customize this on the controller level userescue_from
:Note that this should be done in different view. If you add a
<% if @review.present? %>
to yourreviews/show.html.erb
view you should get your Rails licence revoked as the views one and only job is to display the review.You can also configure the responses on the application level with
config.exceptions_app
.问题是,如果 ID 与数据库中的评论不对应,则
@review
对象将为nil
,并且您的行if @review.valid ?
将抛出错误。你需要一个不同的测试,比如
The problem is that if the ID does not correspond to a review in the database, the
@review
object will benil
, and your lineif @review.valid?
will throw an error.You need a different test, something like