Sinatra捕获自定义错误页面的例外

时间:2015-04-26 17:50:20

标签: ruby exception exception-handling sinatra

我正在尝试处理Modular Sinatra应用程序中的错误。我们通过应用程序引发了各种错误,我写了一些类似的东西来捕捉错误,认为它会分层次地发生。

我用于错误处理的文件如下所示。

#!/usr/bin/env ruby

# @class        class RApp
# @brief        Sinatra main routes overloading for App class
class RApp < Sinatra::Base

  # @fn         not_found do {{{
  # @brief      Not found error page
  not_found do
    render_error 404, _('Not Found'), env['sinatra.error'].message
  end # }}}

  # @fn         error ServiceNotAvailableError do {{{
  # @brief      Handle ServiceNotFoundException, commonly associated with communication
  #             errors with external required services like Ambrosia, Saba
  error ServiceNotAvailableError do
    render_error 503, _('Service Not Available'), env['sinatra.error'].message
  end # }}}

  # @fn         error Exception do {{{
  # @brief      Handle general internal errors
  error Exception do
    render_error 500, _('Internal Server Error'), env['sinatra.error'].message
  end # }}}

  error DBC::InvalidUUIDError do
    "Invalid UUID Error"
  end

  # @fn         def show_error code, title, message, view = nil {{{
  # @brief      Displays the proper message (html or text) based on if the request is XHR or otherwise
  def render_error code, title, message, view = nil
    view = code.to_s if view.nil?

    if request.xhr?
      halt code, message
    else
      halt code, slim(:"error_pages/#{view}", locals: {title: title, message: message})
    end
  end # }}}

  # Just for testing
  get '/errors/:type' do |type|
    raise Object.const_get(type)
  end

end # of class RApp < Sinatra::Base }}}

# vim:ts=2:tw=100:wm=100

我以为它会尝试按照文件中的顺序进行尝试。

问题如何Exception没有捕获所有异常。

例如,我有DBC::InvalidUUIDError就是这样

  • DBC::InvalidUUIDErrror < DBC::Error
  • DBC::Error < RuntimeError
  • 我在Ruby RuntimeError < Exception
  • 中理解

error Exception并没有像我想象的那样捕捉到所有Exception

我做错了吗?或者通常不可能捕获所有异常吗?

注意:除了提供的答案(两个都有效)之外,我还有set :raise_errors, true。您不需要在开发和生产中设置它。默认情况下,它设置为'test'env。

问题的性质是一些例外处理,一些不处理。

2 个答案:

答案 0 :(得分:3)

以下是Sinatra docs

的相关信息
  

Sinatra在开发环境下运行时会安装特殊的not_found和错误处理程序,以便在浏览器中显示漂亮的堆栈跟踪和其他调试信息。

这意味着,当您在开发中运行时,Sinatra会创建一个默认的“catch-all”错误处理程序,其优先级高于error Exception do .. end块。

进入生产模式后,(或通过disable :show_exceptions 禁用dev),您的error Exception do .. end数据块应该会捕获所有例外情况。

请注意,定义的这些error块的顺序无关紧要。

答案 1 :(得分:2)

添加此项以防止Sinatra自己的错误页面干扰您的自定义错误处理程序:

set :show_exceptions, false

默认情况下,设置在开发模式下为true,在生产中为false。

请注意,如果您遵循Sinatra自述文件关于设置set :show_exceptions, :after_handler的建议,这将使您的错误处理程序即使在开发模式下也能运行(至少对于某些异常类),但它也会为生产中的内置错误页面启用未捕获的异常。并且我不清楚它会尊重哪些错误处理程序,以及它将忽略哪些内置调试页面。

编辑:我意识到您还询问了错误处理程序的定义顺序。无所谓; Sinatra首先在app类中查找与异常类的完全匹配,然后在其超类中查找。如果它没有找到任何,它会重复搜索异常的超类等等。因此Exception的处理程序只会被调用,因为没有更接近匹配的异常。