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

问题描述:

我的应用程序(Ruby 1.9.2)可能引发不同的异常,包括网络连接中断。我rescue Exception => e,然后做case/when以不同的方式处理它们,但几个错误直接通过我的案件else如何在“case when”中捕获Errno :: ECONNRESET类?

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 
+1

在多重救援模块中拯救您的错误类别,然后您可以完全避免使用case语句。 – 2015-02-03 14:33:37

这是因为===运营商是如何工作的类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 

呀,红宝石可以有奇怪的语义有时

+4

是的,很奇怪。 1 === 1 => true。 Array === Array => false。 – Nakilon 2010-09-27 07:00:16

+0

呃。我敢打赌'Array === Class'会成真,但现在我很困惑。现在感谢您的评论我无法入睡:/ – Chubas 2010-09-27 07:06:49

+4

当然,现在它是有道理的。在你比较的元素上调用'==='。所以'Class === Array','String ===“foobar”'和'/ foo/===“foobar”'都返回true。 – Chubas 2010-09-27 18:11:16

那么它取决于你是否引用类或常量。 我有例如不得不使用下面的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 

不知道是怎么打的那个。

+0

究竟是什么版本的ruby是“令人困惑的事实”? – 2016-09-29 20:26:37