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
Другие вопросы по тегам