我想在Rails中“伪造” 404页面。 在PHP中,我只发送带有错误代码的标头,如下所示:
header("HTTP/1.0 404 Not Found");
Rails如何做到这一点?
#1楼
由于错误处理程序已移至中间件,因此所选答案在Rails 3.1+中不起作用(请参阅github issue )。
这是我很满意的解决方案。
在ApplicationController :
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 :
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拥有不同的看法。
#2楼
这些将帮助您...
应用控制器
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
#3楼
要测试错误处理,您可以执行以下操作:
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
#4楼
HTTP 404状态
要返回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
ActiveRecord和HTTP 404
还请记住,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
#5楼
您还可以使用渲染文件:
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
您可以选择是否使用布局的位置。
另一种选择是使用“异常”来控制它:
raise ActiveRecord::RecordNotFound, "Record not found."