Иногда бывает нужна очистка по завершении работы некоторого метода. Возможно, должен быть закрыт открытый файл, буферизованные данные должны быть сброшены, и т.п., etc. Если бы существовала только одна точка выхода из метода, мы могли бы уверенно поместить код очистки в одно место и быть уверены, что он будет выполнен; однако возврат из метода может происходить из нескольких точек, или наша очистка может быть пропущена из-за возникновения исключения.
begin file = open("/tmp/some_file", "w") # ... write to the file ... file.close end
В этом примере, если ошибка возникает во время записи файла, файл останется открытым. Также не хочется обращаться к подобной избыточности:
begin file = open("/tmp/some_file", "w") # ... write to the file ... file.close rescue file.close fail # raise an exception end
Это неуклюже, к тому же становится неуправляемым при усложнении кода, поскольку необходимо реагировать на каждые
returnи
break.
По этой причине вводится новое ключевое слово в схему "
begin...rescue...end" --
ensure. Блок
ensureвыполняется независимо от успешности выполнения блока
begin.
begin file = open("/tmp/some_file", "w") # ... write to the file ... rescue # ... handle the exceptions ... ensure file.close # ... and this always happens. end
Возможно использование
ensureбез
rescue, или наоборот, но если они использованы вместе в одном блоке
begin...end,
rescueдолжен предшествовать
ensure.