什么扔掉不能被抓住?

时间:2014-06-13 15:44:58

标签: ruby-on-rails ruby exception-handling devise

我的Ruby on Rails应用程序中的以下代码:

def test
    begin
        puts 'a'
        authenticate_user!
        puts 'b'
    rescue Exception => e
        puts 'c'
    ensure
        puts 'd'
    end
    puts 'e'
end

其中:

  • test是Ruby on Rails中的控制器
  • authenticate_user!是设计Ruby库中的函数
  • 访问它的结果是HTTP 401

打印:

a
d

对我来说,这表明authenticate_user!已经抛出了某种异常,但我们无法抓住它。这怎么可能?

我还尝试了以下救援块:

rescue Object => e
    puts 'c'
rescue e
    puts 'c'
rescue 
    puts 'c'

1 个答案:

答案 0 :(得分:4)

Ruby中有两种类型的错误处理流程。

最常用,最灵活的是begin...rescue

还有throwcatch,它更轻巧。一些Rack库使用这种机制。

最重要的是,有时令人烦恼的是,机制是分开的,如果库使用throw...catch进行程序流,则无法使用begin...rescue拦截消息,因此rescue Exception块将没有被执行。

一般情况下,您不应尝试拦截第三方throw / catch,除非文档建议您可以。这是因为库可能已修改env以设置错误消息/状态。相反,请查找不适用于Rack错误的等效方法,但对于要检查的条件,请返回truefalse。例如,方法user_signed_in?可能更好。


Ruby中如何使用catch的示例:

puts 'a'
x = catch(:mysymbol) do
    puts 'b'
    throw :mysymbol, 'world'
    puts 'c'
end
puts "hello #{x}"

打印

a
b
hello world