如何在“case when”中捕获Errno :: ECONNRESET类?

时间:2010-09-27 06:10:03

标签: ruby exception-handling case errno

我的应用程序(Ruby 1.9.2)可能引发不同的异常,包括网络连接中断。我rescue Exception => e,然后执行case/when以不同的方式处理它们,但有几个错误直接通过我的案例else

rescue Exception => e
    p e.class
    case e.class
        when Errno::ECONNRESET
            p 1
        when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT
            p 2
        else
            p 3
    end
end

打印:

Errno::ECONNRESET
3

2 个答案:

答案 0 :(得分:50)

这是因为===运算符在类Class

上的工作原理

您要评估的对象上的case语句internally calls ===方法。如果您要测试e课程,则只需针对e进行测试,而不是e.class。那是因为e.class会落入when Class的情况,因为,e.class是一个类。

rescue Exception => e
    case e
        when Errno::ECONNRESET
            p 1
        when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT
            p 2
        else
            p 3
    end
end

是的,Ruby有时可能会有奇怪的语义

答案 1 :(得分:1)

这取决于你是引用类还是常量。 例如,我必须使用以下case语句来获得某种类型的检测工作

def fail(exception_error)
exception = exception_error
case exception.class
  when /HTTPClient::ConnectTimeoutError.new/
    status = 'CONNECTION TIMEOUT'
    connection_status = 'DOWN'
  else
    status = 'UNKNOWN FAILURE'
    connection_status = 'DOWN'
end

但那是因为我正在使用实际的异常类而不是常量。 HTTPCLient正在引发一个实际的类对象:

class TimeoutError < RuntimeError
end  
class ConnectTimeoutError < TimeoutError
end

这是一个令人费解的事实:

error = HTTPClient::ConnectTimeoutError.new
HTTPClient::ConnectTimeoutError === error
#=> true
error === HTTPClient::ConnectTimeoutError
#=> false

不知道该怎么做。