My application (Ruby 1.9.2) may raise different exceptions, including net-connection breaks. I rescue Exception => e
, then do case/when
to handle them in defferent ways, but several errors go through my cases straight to 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
Prints:
Errno::ECONNRESET
3
This is because of how the ===
operator works on the class Class
The case
statement internally calls the ===
method on the object you are evaluating against. If you want to test for e
class, you just test against e
, not e.class
. That's because e.class
would fall into the when Class
case, because, well, e.class is a 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
Yeah, Ruby can have weird semantics sometimes
Well it depends upon whether you referencing the class or the constant.
I have for instance had to use the following case statement to get a certain type of detection working
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
But that's because I'm working with the actual Exception Class not the constant.
HTTPCLient is raising an actual class object:
class TimeoutError < RuntimeError
end
class ConnectTimeoutError < TimeoutError
end
Here's a puzzling fact:
error = HTTPClient::ConnectTimeoutError.new
HTTPClient::ConnectTimeoutError === error
#=> true
error === HTTPClient::ConnectTimeoutError
#=> false
Not sure what to make of that.