Как поймать 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
Ответы
Ответ 1
Это связано с тем, как оператор ===
работает над классом 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
Да, у Ruby иногда может быть странная семантика
Ответ 2
Ну, это зависит от того, ссылаетесь ли вы на класс или константу.
Я, например, должен был использовать следующий оператор 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
Не уверен, что с этим делать.