2010-09-27 9 views
28

Mi aplicación (Ruby 1.9.2) puede generar excepciones diferentes, incluidos los saltos de conexión a la red. I rescue Exception => e, luego haga case/when para manejarlos de diferentes maneras, pero varios errores pasan por mis casos directamente al else.Cómo atrapar la clase Errno :: ECONNRESET en "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 

Lienzo:

Errno::ECONNRESET 
3 
+1

Rescata tus clases de error en un bloque de rescate múltiple y luego puedes evitar el enunciado de caso por completo. –

Respuesta

49

Esto es debido a la forma en que el operador === trabaja en la clase Class

El case comunicado internally calls el método === sobre el objeto que se está evaluando en contra. Si desea probar la clase e, simplemente pruebe contra e, no contra e.class. Eso es porque e.class caería en el caso when Class, porque, bueno, e.class es una clase.

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

Sí, Rubí puede tener la semántica raras veces

+4

Sí, raro. 1 === 1 => verdadero. Array === Array => falso. – Nakilon

+0

Uh. Apuesto que 'Array === Class 'daría verdad, pero ahora estoy confundido. Gracias a su comentario ahora no puedo dormir:/ – Chubas

+4

Por supuesto, ahora tiene sentido. El '===' se invoca en el elemento con el que se compara. Entonces 'Class === Array',' String === "foobar" 'y'/foo/=== "foobar" 'devuelven true. – Chubas

1

Bueno, depende de si se hace referencia a la clase o la constante. tengo, por ejemplo, tuvieron que utilizar la declaración de caso siguiente para obtener un determinado tipo de trabajo de detección

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 

Pero eso es porque estoy trabajando con la excepción de clase real no la constante. HttpClient está levantando un objeto real de la clase:

class TimeoutError < RuntimeError 
end 
class ConnectTimeoutError < TimeoutError 
end 

Aquí es un hecho desconcertante:

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

No está seguro de qué hacer con eso.

+0

¿en qué versión de ruby ​​se ejecutó el "hecho desconcertante"? –

Cuestiones relacionadas