ensure и raise
Часть раздела Логика и управление потоком путешествия по Ruby на Coddy — урок 46 из 56.
Еще два элемента дополняют инструментарий обработки ошибок.
ensure — это блок, который выполняется независимо ни от чего: завершился ли begin нормально, перехватила ли ветка rescue исключение или даже если исключение не было перехвачено. Именно здесь вы размещаете код очистки:
begin
puts "opening file"
raise "something broke"
rescue
puts "caught it"
ensure
puts "closing file"
end
# открытие файла
# поймано
# закрытие файлаraise — это способ создания собственного исключения. Передайте строку для сообщения или класс вместе с сообщением:
def withdraw(amount)
raise ArgumentError, "amount must be positive" if amount <= 0
# ... выполните снятие средств
endПринято вызывать исключение raise на раннем этапе, в начале метода, чтобы быстро завершить выполнение, если аргументы неверны. Вызывающая сторона может использовать rescue, если у неё есть разумный способ восстановления, или позволить исключению всплыть выше.
Задание
ЛегкоОпределите метод safe_divide(a, b), который:
- Генерирует исключение
ArgumentErrorс сообщением"b cannot be zero", еслиb == 0 - В противном случае возвращает
a / b
Затем считайте два целых числа из входных данных. Вызовите safe_divide внутри begin / rescue / ensure:
- В случае успеха выведите
Result: <value> - При возникновении
ArgumentErrorвыведитеError: <message> - В блоке
ensureвсегда выводитеDone.
Для входных данных 10 / 2 вывод будет следующим:
Result: 5
Done.Для входных данных 10 / 0:
Error: b cannot be zero
Done.Шпаргалка
ensure выполняется в любом случае (нормальный выход, обработанное или необработанное исключение) — используйте его для очистки ресурсов:
begin
raise "something broke"
rescue
puts "caught it"
ensure
puts "always runs"
endraise создает исключение. Передайте класс и сообщение, чтобы вызвать исключение определенного типа:
raise ArgumentError, "amount must be positive" if amount <= 0Соглашение: вызывайте исключение (raise) в начале метода, чтобы быстро завершить работу при некорректных аргументах.
Попробуйте сами
# TODO: определить safe_divide(a, b), вызывает ArgumentError, когда b == 0
a = gets.to_i
b = gets.to_i
# TODO: begin ... вывести Result; rescue ArgumentError => e ... вывести Error; ensure ... вывести Done.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Строки в деталях
Обзор методов строкИнтерполяция строкИтерация по строкамSplit и JoinИтоги — String Weaver4Блоки, Proc и лямбды
Что такое блок?do..end против фигурных скобокКлючевое слово yieldПараметры блокаProc и лямбдыИтоги: пользовательский итератор7Хеши. Часть 2
Hash.new со значениями по умолчаниюИтерация по хешамВложенные хешиСлияние и преобразованиеИтоги — счетчик частоты10Проект — Учёт студентов
Обзор проектаДобавить студента2Диапазоны
Что такое диапазон?Методы диапазоновДиапазоны в Case / WhenПовторение — практика по диапазонам5Мощь Enumerable
Select и RejectЦепочки MapReduce / Injectcount, all?, any?, none?group_by и partitionsort_by, min_by, max_byИтоги — Data Pipeline8Продвинутые условные конструкции
Case с классами и RegexМножественные значения в whenТернарный операторОднострочные if / unlessПовторение: Классификатор оценок3Двумерные массивы
Основы двумерных массивовДоступ к элементам двумерного массиваИтерация по двумерным массивамРаспространенные 2D-паттерныИтоги: Операции с матрицами6Проект — Менеджер библиотеки
Обзор проектаДобавление книги9Обработка ошибок
Что такое исключение?begin / rescueМножественные блоки rescueensure и raiseИтоги — Безопасный калькулятор