ruby rescue block - ответ более чем одной командой
Я запускаю сценарий с API, который часто истекает. я использую begin/rescue
блоки, чтобы получить его redo
когда это произойдет, но вы хотите записать, что происходит с командной строкой, прежде чем я запустите redo
команда.
begin
#...api query...
rescue ErrorClass
puts("retrying #{id}") && redo
end
К сожалению, приведенный выше скрипт не работает. Выполняется только первая команда.
Я хотел бы заставить блок спасения запускать несколько строк кода следующим образом:
begin
# api query
rescue ErrorClass do ###or:# rescue ErrorClass do |e|
puts "retrying #{id}"
redo
end
но они тоже не работают.
Мне посчастливилось создать отдельный метод для запуска следующим образом:
def example
id = 34314
begin
5/0
rescue ZeroDivisionError
eval(handle_zerodiv_error(id))
end
end
def handle_zerodiv_error(id)
puts "retrying #{id}"
"redo"
end
... это на самом деле работает. Но, на мой взгляд, он требует слишком много строк кода и использует eval, который, по мнению моего наставника, не кошерный.
2 ответа
Вы излишне усложняете вещи, используя &&
или же do
, &&
версия не работает, потому что puts
возвращается nil
по краткой оценке &&
последующая часть не оценивается. Если вы используете ||
или же ;
вместо этого тогда это будет работать:
begin
...
rescue ErrorClass
puts("retrying #{id}") || redo
end
begin
...
rescue ErrorClass
puts("retrying #{id}"); redo
end
но даже в этом нет необходимости. Вы почему-то, кажется, считаете, что вам нужен блок внутри rescue
писать несколько строк, но это не имеет смысла, потому что вы не используете блок с одной строкой. Не существует конструкции Ruby, которая требует блока только при наличии нескольких строк. Итак, просто поместите их в несколько строк:
begin
...
rescue ErrorClass
puts("retrying #{id}")
redo
end
E сть retry
встроенный. Этот пример взят из "Языка программирования Ruby" стр. 162.
require "open-uri"
tries = 0
begin
tries +=1
open("http://www.example.com/"){|f| puts f.readlines}
rescue OpenURI::HTTPError => e
puts e.message
if (tries < 4)
sleep (2**tries) # wait for 2, 4 or 8 seconds
retry # and try again
end
end