2010-09-27 9 views
28

Moja aplikacja (Ruby 1.9.2) może powodować różne wyjątki, w tym przerwy w połączeniach sieciowych. I rescue Exception => e, następnie wykonaj case/when, aby obsłużyć je na różne sposoby, ale kilka błędów przechodzi przez moje przypadki prosto do else.Jak złapać Errno :: ECONNRESET klasy w "case when"?

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 

Wydruki:

Errno::ECONNRESET 
3 
+1

Ratuj swoje klasy błędów w bloku ratunkowym, a następnie całkowicie unikaj instrukcji case. –

Odpowiedz

49

To dlatego, jak operator === działa od klasy Class

case oświadczenie internally calls metoda === na obiekcie jesteś oceniającego przeciw. Jeśli chcesz przetestować klasę e, po prostu przetestuj przed e, a nie e.class. To dlatego, że e.class wpadłoby w przypadku when Class, ponieważ, cóż, e.class jest klasą.

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

Tak, Ruby może mieć dziwne semantykę czasami

+4

Tak, dziwne. 1 === 1 => prawda. Array === Array => false. – Nakilon

+0

Uh. Założę się, że "Array === Class" dałoby się prawdziwe, ale teraz jestem zdezorientowany. Dzięki waszemu komentarzowi teraz nie mogę spać:/ – Chubas

+4

Oczywiście, teraz ma to sens. '===' jest wywołany na elemencie, z którym się porównujesz. Tak więc 'Class === Array',' String === "foobar" 'i'/foo/=== "foobar" 'all zwracają true. – Chubas

1

To zależy od tego, czy odwołanie do klasy lub stałej. mam na przykład musiałem użyć następujące oświadczenie przypadku, aby uzyskać pewien rodzaj detekcji roboczej

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 

Ale to dlatego, że pracuję z rzeczywistą klasy wyjątek nie stała. httpclient jest podniesienie rzeczywistego obiektu klasy:

class TimeoutError < RuntimeError 
end 
class ConnectTimeoutError < TimeoutError 
end 

Oto zaskakujący fakt:

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

nie wiesz, co zrobić z tym.

+0

, w jakiej wersji ruby ​​występował "zagadkowy fakt"? –

Powiązane problemy