33

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 
1
  • 1
    Rescue your error classes in a multi-rescue block and then you can avoid the case statement entirely. Commented Feb 3, 2015 at 14:33

2 Answers 2

59

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

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, weird. 1 === 1 => true. Array === Array => false.
Uh. I'd bet Array === Class would give true, but now I'm confused. Thanks to your comment now I can't sleep :/
Of course, now it makes sense. The === is called on the element you're comparing to. So Class === Array, String === "foobar" and /foo/ === "foobar" all return true.
3

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.

1 Comment

what version of ruby was the 'puzzling fact' run in?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.