我想在Rails中“伪造”一个404页面。在PHP中,我只会发送一个带有错误代码的报头:
header("HTTP/1.0 404 Not Found");
Rails如何做到这一点?
我想在Rails中“伪造”一个404页面。在PHP中,我只会发送一个带有错误代码的报头:
header("HTTP/1.0 404 Not Found");
Rails如何做到这一点?
当前回答
为了测试错误处理,你可以这样做:
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
其他回答
Raising ActionController::RoutingError('not found')对我来说总是感觉有点奇怪——在未经过身份验证的用户的情况下,这个错误并不反映现实——路由被找到了,用户只是没有经过身份验证。
我偶然发现config。action_dispatch。我认为在某些情况下,这是一个更优雅的解决方案的问题:
# application.rb
config.action_dispatch.rescue_responses = {
'UnauthenticatedError' => :not_found
}
# my_controller.rb
before_action :verify_user_authentication
def verify_user_authentication
raise UnauthenticatedError if !user_authenticated?
end
这种方法的好处在于:
它像普通的ActionController::RoutingError一样挂钩到现有的错误处理中间件中,但是在开发环境中你会得到一个更有意义的错误消息 它将正确地将状态设置为您在rescue_responses散列中指定的任何状态(在本例中为404 - not_found) 您不必编写一个需要在任何地方都可用的not_found方法。
我想对任何不是管理员的登录用户抛出一个“正常的”404,所以我最终在Rails 5中写了这样的东西:
class AdminController < ApplicationController
before_action :blackhole_admin
private
def blackhole_admin
return if current_user.admin?
raise ActionController::RoutingError, 'Not Found'
rescue ActionController::RoutingError
render file: "#{Rails.root}/public/404", layout: false, status: :not_found
end
end
不要自己渲染404页面,没有理由;Rails已经内置了这个功能。如果你想显示一个404页面,在ApplicationController中创建一个render_404方法(或者我称之为not_found),如下所示:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Rails还以同样的方式处理AbstractController::ActionNotFound和ActiveRecord::RecordNotFound。
这样做有两个好处:
1)它使用Rails内置的rescue_from处理程序来呈现404页面 2)它会中断代码的执行,让你做一些不错的事情,比如:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
而不用写丑陋的条件语句。
作为奖励,它在测试中也非常容易处理。例如,在rspec集成测试中:
# RSpec 1
lambda {
visit '/something/you/want/to/404'
}.should raise_error(ActionController::RoutingError)
# RSpec 2+
expect {
get '/something/you/want/to/404'
}.to raise_error(ActionController::RoutingError)
和小型试验:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
OR从控制器动作中找不到的Rails渲染404中引用更多信息
为了测试错误处理,你可以这样做:
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
<%= render file: 'public/404', status: 404, formats: [:html] %>
只需将此添加到要呈现到404错误页面的页面,就完成了。