2

I'd like to retry a function with different params depending on the result of the first iteration:

Giving a retry function like follow:

 def retry_on_fail(**args)
   yield
 rescue StandardError => e
    args = args.merge(different_param => true) if e.class == `specific_error`
    retry

Is there a way to do so? I didn't find it yet... Thanks!

2 Answers2

2

You can yield however many times you want in a method and the trick is really passing the arguments to the block:

# given
class SpecificError < StandardError; end

def retry_on_fail(**args)
  yield(args)
rescue SpecificError 
  yield(args.merge(different_param: true))
end
retry_on_fail do |args|
  raise SpecificError if args.empty?
  args
end
# returns { different_param: true }

There is also a slight differnce here flow wise - retry runs the whole method from the top and this will just call the block again. If thats what you want you could do:

def retry_on_fail(**args)
  yield(args)
rescue SpecificError 
  args.merge!(different_param: true) 
  retry
end

But this has the potential to create an endless loop if the block raises the same exception again.

max
  • 96,212
  • 14
  • 104
  • 165
  • 2
    Note that I intentionally avoided `rescue StandardError` as thats a prime example of Pokémon exception handling. Only rescue exceptions that you know what to do with. – max Nov 23 '20 at 10:01
0

Try this

def retry_on_fail(**args)
  rescue_args = args 
  begin
    yield(rescue_args)
  rescue StandardError => e
    rescue_args = rescue_args.merge(different_param => true) if e.class == `specific_error`
    retry
  end  
end
Ritesh Choudhary
  • 772
  • 1
  • 4
  • 12