Не так давно я обнаружил одну интересную фичу в Руби. Мне показалась, что она может быть весьма полезной в определенных ситуациях. Тем не менее, я пришел к выводу, что этот трюк не так уж частно используется в коде, так как за многие годы программирования наткнулся я на него только сейчас. Идея в том, что мы можем дать еще один шанс коду, который привел к исключению (exception) и запустить его повторно. Давайте посмотрим, насколько легко это делается в руби.
Мы оборачиваем определенный код в блок begin и, когда нам нужно будет запустить этот блок еще раз, просто пишем ключевое слово retry. Это может быть использовано в случае с подключением к внешним сервисам или API, которые могут работать нестабильно и иногда выдавать timeout или другие ошибки.
Итак, давайте рассмотрим один простенький пример применения этому. Мы напишем метод, который будет имитировать соединение и с вероятностью примерно в 30 процентов будет выдавать исключение. Чтобы это сделать, внутри мы будем генерировать случайное число и если этим числом окажется единица — выдавать исключение.
def connect
tries = 0
max_tries = 3
begin
raise if rand(3) == 1
rescue
tries += 1
if tries == max_tries
raise "We have tried #{tries} times but it still fails"
else
retry
end
end
end
Здесь у нас есть переменная tries, в которой мы подсчитываем сколько раз мы уже попытались запустить указанный блок. Это необходимо для того чтобы не допустить бесконечный цикл. Переменная max_tries указывает максимальное число попыток, после которого мы должны перестать пытаться запустить код и все таки выдать ошибку. Как видите, вся магия происходит в rescue блоке, когда мы вызываем retry.
Автор: heel