¿Cómo coger la clase Errno:: ECONNRESET en "caso cuando"?


Mi aplicación (Ruby 1.9.2) puede generar diferentes excepciones, incluyendo interrupciones de conexión a la red. Yo rescue Exception => e, luego hago case/when para manejarlos de maneras diferentes, pero varios errores pasan por mis casos directamente a 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

Impresiones:

Errno::ECONNRESET
3
Author: Nakilon, 2010-09-27

2 answers

Esto se debe a cómo funciona el operador === en la clase Class

La instrucción case llama internamente a el método === en el objeto contra el que está evaluando. Si quieres probar para la clase e, solo prueba contra e, no 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í, Ruby puede tener semántica rara a veces

 49
Author: Chubas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-27 06:41:37

Bueno, depende de si se hace referencia a la clase o a la constante. Por ejemplo, he tenido que utilizar la siguiente sentencia case para obtener un cierto tipo de detección de trabajo

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 Clase de Excepción real no con la constante. HttpClient está levantando un objeto de clase real:

class TimeoutError < RuntimeError
end  
class ConnectTimeoutError < TimeoutError
end

Aquí hay un hecho desconcertante:

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

No estoy seguro de qué hacer con eso.

 1
Author: Ashley Raiteri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-25 18:44:42