Question

I'm running a script with an API that often times out. I'm using begin/rescue blocks to get it to redo when this happens, but want to log what is happening to the command line before I run the redo command.

begin
#...api query...
rescue ErrorClass
  puts("retrying #{id}") && redo
end

Unfortunately the above script doesn't work. Only the first command is run.

I would like to force the rescue block to run multiple lines of code like so:

begin
 # api query
rescue ErrorClass do ###or:# rescue ErrorClass do |e|
  puts "retrying #{id}"
  redo
 end

but those don't work either.

I've had luck creating a separate method to run like so:

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

...that actually works. But it requires too many lines of code in my opinion and it uses eval which is not kosher by any means according to my mentor(s).

Was it helpful?

Solution

You are unnecessarily complicating things by using && or do. The && version does not work because puts returns nil, so by shortcut evaluation of &&, the part to follow is not evaluated. If you use || or ; instead, then it will work:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}") || redo
end

begin
  ...
rescue ErrorClass
  puts("retrying #{id}"); redo
end

but even this is not necessary. You somehow seem to believe that you need a block within rescue to write multiple lines, but that does not make sense because you are not using a block with single line. There is no Ruby construction that requires a block only when you have multiple lines. So, just put them in multiple lines:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}")
  redo
end

OTHER TIPS

There is a retry built in. This example is from "The Ruby Programming Language" pg 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top