我正在嘗試向我的 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
但是,我的專案不斷崩潰而不是顯示訊息。如果有什么辦法可以使這項作業?謝謝。
uj5u.com熱心網友回復:
問題是如果 ID 與資料庫中的評論不對應,則@review物件將為nil,并且您的行將if @review.valid?引發錯誤。
你需要一個不同的測驗,比如
<% if @review.present? %>
<div class='review-header'>
....
</div>
<% else %>
Review does not exist.
<% end %>
uj5u.com熱心網友回復:
問題的整個設定實際上被破壞了。
您不需要為 id 添加模型驗證,因為 id 在您插入記錄時由資料庫自動生成。在大多數資料庫中,主鍵也是不可為空的。添加驗證實際上會破壞模型,因為這會阻止您在不手動分配 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 將ActiveRecord::RecordNotFound通過呈現位于public/404.html并回傳 404 狀態代碼的靜態 HTML 頁面來處理未捕獲的例外。如果您想在控制器級別自定義它,請使用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。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/432288.html
