我想在Rails中「僞造」 404頁面。 在PHP中,我只發送帶有錯誤代碼的標頭,以下所示: html
header("HTTP/1.0 404 Not Found");
Rails如何作到這一點? git
因爲錯誤處理程序已移至中間件,所以所選答案在Rails 3.1+中不起做用(請參閱github issue )。 github
這是我很滿意的解決方案。 app
在ApplicationController
: less
unless Rails.application.config.consider_all_requests_local rescue_from Exception, with: :handle_exception end def not_found raise ActionController::RoutingError.new('Not Found') end def handle_exception(exception=nil) if exception logger = Logger.new(STDOUT) logger.debug "Exception Message: #{exception.message} \n" logger.debug "Exception Class: #{exception.class} \n" logger.debug "Exception Backtrace: \n" logger.debug exception.backtrace.join("\n") if [ActionController::RoutingError, ActionController::UnknownController, ActionController::UnknownAction].include?(exception.class) return render_404 else return render_500 end end end def render_404 respond_to do |format| format.html { render template: 'errors/not_found', layout: 'layouts/application', status: 404 } format.all { render nothing: true, status: 404 } end end def render_500 respond_to do |format| format.html { render template: 'errors/internal_server_error', layout: 'layouts/application', status: 500 } format.all { render nothing: true, status: 500} end end
並在application.rb
: ide
config.after_initialize do |app| app.routes.append{ match '*a', :to => 'application#not_found' } unless config.consider_all_requests_local end
在個人資源(顯示,編輯,更新,刪除)中: 佈局
@resource = Resource.find(params[:id]) or not_found
固然能夠改善這一點,可是至少在不覆蓋Rails核心功能的狀況下,我對not_found和internal_error擁有不一樣的見解。 測試
這些將幫助您... spa
應用控制器 debug
class ApplicationController < ActionController::Base protect_from_forgery unless Rails.application.config.consider_all_requests_local rescue_from ActionController::RoutingError, ActionController::UnknownController, ::AbstractController::ActionNotFound, ActiveRecord::RecordNotFound, with: lambda { |exception| render_error 404, exception } end private def render_error(status, exception) Rails.logger.error status.to_s + " " + exception.message.to_s Rails.logger.error exception.backtrace.join("\n") respond_to do |format| format.html { render template: "errors/error_#{status}",status: status } format.all { render nothing: true, status: status } end end end
錯誤控制器
class ErrorsController < ApplicationController def error_404 @not_found_path = params[:not_found] end end
views / errors / error_404.html.haml
.site .services-page .error-template %h1 Oops! %h2 404 Not Found .error-details Sorry, an error has occured, Requested page not found! You tried to access '#{@not_found_path}', which is not a valid page. .error-actions %a.button_simple_orange.btn.btn-primary.btn-lg{href: root_path} %span.glyphicon.glyphicon-home Take Me Home
要測試錯誤處理,您能夠執行如下操做:
feature ErrorHandling do before do Rails.application.config.consider_all_requests_local = false Rails.application.config.action_dispatch.show_exceptions = true end scenario 'renders not_found template' do visit '/blah' expect(page).to have_content "The page you were looking for doesn't exist." end end
要返回404標頭,只需對render方法使用:status
選項。
def action # here the code render :status => 404 end
若是要呈現標準404頁面,則可使用方法提取功能。
def render_404 respond_to do |format| format.html { render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found } format.xml { head :not_found } format.any { head :not_found } end end
並在行動中稱呼它
def action # here the code render_404 end
若是要使操做呈現錯誤頁面並中止,只需使用return語句便可。
def action render_404 and return if params[:something].blank? # here the code that will never be executed end
還請記住,Rails會挽救一些ActiveRecord錯誤,例如顯示404錯誤頁面的ActiveRecord::RecordNotFound
。
這意味着您無需本身挽救該動做
def show user = User.find(params[:id]) end
當用戶不存在時, User.find
引起ActiveRecord::RecordNotFound
。 這是一個很是強大的功能。 看下面的代碼
def show user = User.find_by_email(params[:email]) or raise("not found") # ... end
您能夠經過將檢查委託給Rails來簡化。 只需使用爆炸版本。
def show user = User.find_by_email!(params[:email]) # ... end
您還可使用渲染文件:
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
您能夠選擇是否使用佈局的位置。
另外一種選擇是使用「異常」來控制它:
raise ActiveRecord::RecordNotFound, "Record not found."