Rails 3中的动态错误页面

Pau*_*ber 38 error-handling exception-handling ruby-on-rails actionview ruby-on-rails-3

在Rails 2.3.x中,您可以render_optional_error_file像这样覆盖:

# ApplicationController.rb
protected
  def render_optional_error_file(status_code)
    render :template => "errors/500", :status => 500, :layout => 'application'
  end
Run Code Online (Sandbox Code Playgroud)

但是,Rails 3不再具有render_optional_error_file.相反,你需要覆盖rescue_action_in_public,你可以这样做:

# config/initializers/error_page.rb
module ActionDispatch
  class ShowExceptions

    protected    
      def rescue_action_in_public(exception)
        status = status_code(exception).to_s

        template = ActionView::Base.new(["#{Rails.root}/app/views"])
        if ["404"].include?(status)
          file = "/errors/404.html.erb"
        else
          file = "/errors/500.html.erb"
        end        
        body = template.render(:file => file)

        render(status, body)
      end

  end
end
Run Code Online (Sandbox Code Playgroud)

这有效,但不使用应用程序的布局.但是,如果您指定布局路径,如下所示:

body = template.render(:file => file, :layout => "layouts/application") # line 15
Run Code Online (Sandbox Code Playgroud)

你得到一个Error during failsafe response: ActionView::Template::Error.

application.html.erb:4的第4行是:

<%= stylesheet_link_tag "app", "jquery-ui", "jquery.fancybox", :cache => "all" %>
Run Code Online (Sandbox Code Playgroud)

无论ActionView通常用于渲染模板的是什么都没有加载.

堆栈跟踪是:

  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:794:in `join'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:794:in `rails_asset_id'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:817:in `rewrite_asset_path'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:746:in `compute_public_path'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:424:in `path_to_stylesheet'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:875:in `ensure_stylesheet_sources!'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:874:in `each'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:874:in `ensure_stylesheet_sources!'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/helpers/asset_tag_helper.rb:512:in `stylesheet_link_tag'
  /data/sites/fundraisers-stage/releases/20110316194843/app/views/layouts/application.html.erb:4:in `_app_views_layouts_application_html_erb___19482063_70294907435920_0'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/template.rb:135:in `send'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/template.rb:135:in `render'
  /var/lib/gems/1.8/gems/activesupport-3.0.5/lib/active_support/notifications.rb:54:in `instrument'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/template.rb:127:in `render'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/render/layouts.rb:80:in `_render_layout'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/render/rendering.rb:62:in `_render_template'
  /var/lib/gems/1.8/gems/activesupport-3.0.5/lib/active_support/notifications.rb:52:in `instrument'
  /var/lib/gems/1.8/gems/activesupport-3.0.5/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
  /var/lib/gems/1.8/gems/activesupport-3.0.5/lib/active_support/notifications.rb:52:in `instrument'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/render/rendering.rb:56:in `_render_template'
  /var/lib/gems/1.8/gems/actionpack-3.0.5/lib/action_view/render/rendering.rb:26:in `render'
  /data/sites/fundraisers-stage/releases/20110316194843/config/initializers/error_pages.rb:15:in `rescue_action_in_public'
Run Code Online (Sandbox Code Playgroud)

doc*_*hat 55

在rails 3.2中,它比那更容易:

将此添加到config/application.rb:

config.exceptions_app = self.routes
Run Code Online (Sandbox Code Playgroud)

这会导致错误通过路由器路由.然后你只需添加到config/routes.rb:

match "/404", :to => "errors#not_found"
Run Code Online (Sandbox Code Playgroud)

我从ByJoséValim 的博客文章" 我在Rails 3.2中最喜欢的五个隐藏功能 "中获得了第3项中的这些信息.

  • `config.exceptions_app = self.routes`适用于404错误,但它也可以防止500错误加载500.html文件.是否可以设置404从应用程序加载但保持从静态文件加载500错误?(因为如果应用程序中出现问题,可能会导致错误消息中断.)谢谢! (3认同)

mne*_*son 51

我建议改用rescue_from.您只需从特定错误中解救而不是覆盖rescue_action_in_public.在处理用户定义的错误或特定于控制器的错误时,这尤其有用.

# ApplicationController
rescue_from ActionController::RoutingError, :with => :render_404
rescue_from ActionController::UnknownAction, :with => :render_404
rescue_from ActiveRecord::RecordNotFound, :with => :render_404
rescue_from MyApp::CustomError, :with => :custom_error_resolution

def render_404
  if /(jpe?g|png|gif)/i === request.path
    render :text => "404 Not Found", :status => 404
  else
    render :template => "shared/404", :layout => 'application', :status => 404
  end
end

# UsersController
rescue_from MyApp::SomeReallySpecificUserError, :with => :user_controller_resolution
Run Code Online (Sandbox Code Playgroud)

http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html