Как отловить класс Errno::ECONNRESET в "случае, когда"?

Мое приложение (Ruby 1.9.2) может вызывать различные исключения, включая разрывы сетевого соединения. я rescue Exception => eтогда делай case/when обращаться с ними по-разному, но несколько ошибок проходят через мои дела прямо к 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

Печать:

Errno::ECONNRESET
3

2 ответа

Решение

Это из-за того, как === оператор работает на уроке Class

case Заявление внутренне вызывает === метод объекта, с которым вы оцениваете. Если вы хотите проверить на e класс, вы просто проверить против eне e.class, Это потому что e.class попадет в when Class случай, потому что, ну, e.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

Да, у Руби иногда может быть странная семантика

Ну, это зависит от того, ссылаетесь ли вы на класс или на константу. Мне, например, пришлось использовать следующую инструкцию case, чтобы заставить работать определенный тип обнаружения

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

Но это потому, что я работаю с классом исключений, а не с константой. HTTPCLient вызывает фактический объект класса:

class TimeoutError < RuntimeError
end  
class ConnectTimeoutError < TimeoutError
end

Вот загадочный факт:

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

Не уверен, что с этим делать.

Другие вопросы по тегам