如何在Rails中实现动态404,500等错误页面?

时间:2009-06-03 05:02:25

标签: ruby-on-rails ruby

如何在Rails中实现动态的自定义错误页面?

例如,使用您的application.html.erb布局的自定义404错误页面以及页面中的一些动态字段。

另外,如何从本地机器测试?

5 个答案:

答案 0 :(得分:13)

我查看了Google上有关如何执行此操作的一些博客文章,遗憾的是,大多数人似乎依赖于污染您的ApplicationController。

我所做的是使用404消息创建模板,然后使用该模板从rake任务更新public / 404.html文件:

# Rake file to generate static 404 page

file "public/404.html" => ["app/views/layouts/application.html.erb"] do |t|
    print "Updating 404 page\n"
    `curl --silent http://locahost/content/error404 -o public/404.html`
end 

现在每当我更新我的全局布局时,404页面都会自动更新。

答案 1 :(得分:9)

只需将以下内容添加到ApplicationController:

  rescue_from ActiveRecord::RecordNotFound, :with => :render_record_not_found

  # Catch record not found for Active Record
  def render_record_not_found
    render :template => "shared/catchmissingpage", :layout => false, :status => 404
  end

  # Catches any missing methods and calls the general render_missing_page method
  def method_missing(*args)
    render_missing_page # calls my common 404 rendering method
  end

  # General method to render a 404
  def render_missing_page
    render :template => "shared/catchmissingpage", :layout => false, :status => 404
  end

您可以自定义渲染调用(使用模板,使用布局等)并以这种方式捕获错误。现在它为你捕获了缺少的方法和record_not_found,但也许在某些情况下你想要显示500错误页面,这样你就可以继续使用这种方法并使它适合你。

对于从本地计算机进行测试,它就是这样的。如果您只希望它在生产模式下工作,请添加

 if ENV['RAILS_ENV'] == 'production'

你没事。

答案 2 :(得分:6)

检查Henrik Nyh's post。其他人也可以通过谷歌找到。

背后的想法:Rails似乎为404错误呈现public/404.html

  • 如果要显示静态字段,则可以覆盖页面
  • 对于动态内容,您似乎可以覆盖框架方法以挂钩并重定向以呈现动态页面。

ActionController::Rescue定义了rescue_action_in_public来调用render_optional_error_file

答案 3 :(得分:3)

如果您决定创建动态404(或其他状态代码)页面,请务必从/public中删除相应的html文件(如果存在)

答案 4 :(得分:1)

在测试方面,一个非常好的方法(至少用于开发目的)是使用Passenger并将rails环境设置为生产(或在站点配置中注释掉“RailsEnv development”)。至少这种方式你可以模仿它在生产中的运作方式。

但是,为了完成这项工作,我有各种各样的设置文件,这些文件在启动时被解析并根据环境被选中。其中一个设置是是否显示错误页面(AppSettings.show_page_errors?)。然后在我的应用程序控制器中,我有

  if !AppSettings.show_page_errors?
    alias_method :rescue_action_locally, :rescue_action_in_public
  end

因此,它通常设置为默认设置,但有时我真的需要查看到底发生了什么,所以我可以在生产时将其关闭。

另一步是使用自定义页面。在我的情况下,我有基于错误的模板,还包括提交到谷歌表单的表单(因为我的服务器可能被破坏)。为此,请在应用程序控制器中添加(并根据需要进行更改):

def render_optional_error_file(status_code)
  status = interpret_status(status_code)
  render :template => "/errors/#{status.to_s[0,3]}.html.haml", :status => status, :layout => 'application.html.haml' if [404, 422, 500].include?(status)
  render :template => "/errors/unknown.html.haml", :status => status, :layout => 'application.html.haml' unless [404, 422, 500].include?(status)
end

这将使用模板呈现状态代码404,422和500,否则使用未知。如果您需要处理其他人,只需更新此方法并添加模板即可。