Ruby Исключения
Исключения и выполнение всегда связаны. Если вы открываете файл, которого не существует, и не обрабатываете эту ситуацию должным образом, ваша программа считается низкокачественной.
Если возникает исключение, программа останавливается. Исключения используются для обработки различных типов ошибок, которые могут возникнуть во время выполнения программы, чтобы можно было предпринять соответствующие действия, не позволяя программе полностью остановиться.
Ruby предоставляет совершенный механизм для обработки исключений. Мы можемbegin/endприкрепить код, который может вызвать исключение, в блок и использоватьrescue-предложение, чтобы сообщить Ruby, какие именно типы исключений обрабатывать.
Синтаксис
отbeginдоrescueВсё, что внутри, защищено. Если во время выполнения блока возникает исключение, управление передаётсяrescueиendблок между ними.
Дляbeginкаждого в блокеrescue-предложение, Ruby сравнивает возникшее исключение с каждым параметром по очереди. Если исключение, указанное в предложении rescue, имеет тот же тип, что и текущее возникшее исключение, или является родительским классом этого исключения, то совпадение успешно.
Если исключение не соответствует всем указанным типам ошибок, мы можем после всехrescue-предложений использоватьelse-предложение.
Примеры
В приведенном выше примере выводится результат. Вы можете видеть,STDINзаменилfile, потому чтооткрытиене удалось.
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Использованиеretryоператора
Вы можете использоватьrescueблок для перехвата исключений, затем использоватьretryоператор для выполнения с началаbeginблок.
Синтаксис
Примеры
Ниже приведён поток обработки:
- При открытии возникает исключение.
- Переход к rescue. fname переназначается.
- Переход к началу begin через retry.
- На этот раз файл успешно открывается.
- Продолжить базовый процесс.
Примечание:Если переименованный файл не существует, этот пример кода будет пытаться бесконечно. Поэтому при обработке исключений используйте с осторожностьюretry。
Использованиеraiseинструкции
Вы можете использоватьraiseинструкцию для вызова исключения. Следующий метод вызывает исключение при вызове. Его второе сообщение будет выведено.
Синтаксис
Первая форма просто повторно возбуждает текущее исключение (или возбуждает RuntimeError, если текущего исключения нет). Она используется в обработчиках исключений, которым нужно объяснить исключение, прежде чем передать его дальше.
Вторая форма создаёт новоеRuntimeErrorисключение, устанавливая его сообщение в заданную строку. Затем исключение выбрасывается в стек вызовов.
Третья форма создаёт исключение, используя первый параметр, затем устанавливает связанное с ним сообщение во второй параметр.
Четвёртая форма похожа на третью, и вы можете добавить любые дополнительные условные операторы (такие какunless), чтобы возбудить исключение.
Примеры
Приведённый выше пример выводит:
I am before the raise. I am rescued. I am after the begin block.
Ещё одна демонстрацияraiseпример использования:
Примеры
Приведённый выше пример выводит:
A test exception. ["main.rb:4"]
Использованиеensureоператора
Иногда, независимо от того, возбуждается ли исключение или нет, необходимо обеспечить, чтобы некоторая обработка завершилась при завершении блока кода. Например, вы могли открыть файл при входе, и при выходе из блока нужно убедиться, что файл закрыт.
ensureКонструкция ensure делает именно это. ensure размещается после последней конструкции rescue и содержит блок кода, который всегда выполняется при завершении блока. Неважно, завершается ли блок нормально, возбуждает ли и обрабатывает исключение или завершается из-за неперехваченного исключения,ensureблок всегда будет выполняться.
Синтаксис
Примеры
Приведённый выше пример выводит:
A test exception. ["main.rb:4"] Ensuring execution
Использованиеelseоператора
Если предусмотрено предложениеelse, оно обычно размещается после предложенияrescue, перед любымensureперед.
elseТело этого предложения выполняется только тогда, когда основное тело кода не вызывает исключения.
Синтаксис
Примеры
Приведённый выше пример выводит:
I'm not raising exception Congratulations-- no errors! Ensuring execution
Используя переменную $!, можно захватить сообщение о возбуждённом исключении.
Catch и Throw
Механизм исключений с помощью raise и rescue может прервать выполнение при возникновении ошибки. Иногда во время нормальной обработки нужно выйти из некоторых глубоко вложенных структур. Здесь пригодятся catch и throw.
catchопределяет блок, который использует заданное имя (которое может быть Symbol или String) в качестве метки. Блок выполняется как обычно, пока не встретит throw.
Синтаксис
Примеры
В следующем примере, если пользователь вводит '!' в ответ на любое приглашение, throw используется для завершения взаимодействия с пользователем.
Примеры
Приведённая выше программа требует взаимодействия с человеком; вы можете попробовать её на своём компьютере. Приведённый выше пример выводит:
Name: Ruby on Rails Age: 3 Sex: ! Name:Just Ruby
Класс Exception
Стандартные классы и модули Ruby возбуждают исключения. Все классы исключений образуют иерархию, включая класс Exception на вершине. Следующий уровень вниз состоит из семи различных типов:
- Прервать
- NoMemoryError
- SignalException
- ScriptError
- StandardError
- SystemExit
Fatal — ещё одно исключение на этом уровне, но интерпретатор Ruby использует его только внутренне.
У ScriptError и StandardError есть несколько подклассов, но здесь нам не нужно разбираться в этих деталях. Самое важное — создавать собственные классы исключений, которые должны быть подклассами класса Exception или его потомков.
Давайте посмотрим на пример:
Примеры
Теперь посмотрите на следующий пример, в котором будет использоваться вышеуказанное исключение:
Примеры
Здесь самая важная строка — raiseFileSaveError.new($!). Мы вызываем raise, чтобы сообщить, что произошло исключение, передавая новый экземпляр FileSaveError, потому что конкретное исключение привело к сбою записи данных.
Другие расширения