Ruby中的Sinatra错误处理

tjr*_*ess 10 ruby error-handling sinatra

我有一个简单的Sinatra休息,我无法捕获错误.我也承认我对Ruby和Sinatra很新.

当我在post端点中引发并出错时,我想报告传入的文档.我需要1)处理post结果中的错误(我可以访问@incoming)或2)将传入的文档传递给错误并在那里报告.

什么是更好的选择,选项1或选项2?

  • 如果我留在选项1,我如何防止错误收到错误(因为它似乎现在正在做)
  • 如果我转到选项2,如何将传入传递给错误?

以下是我的代码示例:

post ('/result') do 

  begin  
  @incoming = JSON.parse(request.body.read)

  //do something that causes an error
  rescue
     e = env['sinatra.error']
     url = request.url
     ip = request.ip

     @actlogpassblock = {  :message => e.message,
                        :path => url,
                        :ip => ip,
                        :timestamp => Time.new,
                        :type => "500",
                        :sub => "RES",
                        :payload => @incoming
                      }        
    action_log.insert(@actlogpassblock)
    status 500 
  end
end

error do
   status 500 
   e = env['sinatra.error']
   url = request.url
   ip = request.ip
   backtrace = "Application error\n#{e}\n#{e.backtrace.join("\n")}"

  @actlogpassblock = {  :message => e.message,
                        :path => url,
                        :ip => ip,
                        :timestamp => Time.new,
                        :type => "500",
                        :backtrace => backtrace
                      }        
  action_log.insert(@actlogpassblock)
  {:result => 'Ah Shucks! Something went wrong'}.to_json
end
Run Code Online (Sandbox Code Playgroud)

7st*_*tud 19

如果我留在选项1,我如何防止错误收到错误(因为它似乎现在正在做)

根据文件:

每当从路由块引发异常时,都会调用错误处理程序...

但是,这仅适用于未捕获的异常.试试这个:

require 'sinatra'
set :show_exceptions, false

get '/' do
  begin
    raise ZeroDivisionError
  rescue ZeroDivisionError
    "rescue clause"
  end
end

error do
  "sinatra error handler" 
end
Run Code Online (Sandbox Code Playgroud)

然后尝试这个:

get '/' do
  raise ZeroDivisionError
end

error do
  "sinatra error handler" 
end
Run Code Online (Sandbox Code Playgroud)

此外,您可以定制错误处理程序以仅捕获某些异常,从而避免一些异常,例如

error IndexError do ...
Run Code Online (Sandbox Code Playgroud)

要么

error MyCustomException do ...
Run Code Online (Sandbox Code Playgroud)

要么

error 400..510 do
Run Code Online (Sandbox Code Playgroud)

但是对于catch所有版本:

error do
Run Code Online (Sandbox Code Playgroud)

你不能阻止在路由块中发生未捕获的异常时执行...除非:

但是,如果Sinatra :raise_errors:show_exceptions配置选项都设置为false ,则只会调用错误处理程序 ...

:raise_errors在"test"环境中默认为true,在其他环境中默认为false.

:show_exceptions值在"development"环境中默认为true,在其他环境中默认为false

辛特拉的作者曾说:"这[行为]是有意的.这个想法是错误块会隐藏问题而你通常不希望在开发模式下这样做.

https://github.com/sul-dlss/sdr-services-app/blob/master/Sinatra-error-handling.md

如果我转到选项2,如何将传入传递给错误?

在错误块内可以看到在路径块内创建的@variable.试试这个:

require 'sinatra'
set :show_exceptions, false

get '/' do
  @incoming = "hello world"    #create @variable
  raise ZeroDivisionError
end

error ZeroDivisionError do
  @incoming                    #retrieve @variable
end
Run Code Online (Sandbox Code Playgroud)

http://localhost:4567浏览器中输入URL后,您应该在返回的网页上看到"hello world".

之所以有效,是因为@variable在创建@variable时将自身附加到自身的任何对象上; 同样,当召唤@variable时,它会从当时的任何自身对象中检索出来.当Sinatra执行路径块或错误块时,它将self设置为同一个对象.

选项2似乎很好,因为它将错误处理代码与应用程序代码分开.