我想在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."