๐ŸŽ“ A1Learner
๐Ÿ”
0 of 34 lessons completed

Ruby Retry and Ensure

ensure runs a closing step whatever happened inside a begin block. retry runs the block again, and a counter keeps it from looping forever.

ensure runs either way

The first block divides with no trouble, and the second block divides by zero and is rescued. The ensure line prints at the end of both blocks.

begin
  total = 10 / 2
  puts total
ensure
  puts "First block closed"
end
begin
  total = 10 / 0
  puts total
rescue ZeroDivisionError
  puts "Divided by zero"
ensure
  puts "Second block closed"
end

retry with a counter

The attempts counter sits outside the block and grows on each run. The raise fires on the first two tries, so retry runs the block until the third try works.

attempts = 0
begin
  attempts += 1
  puts "Try #{attempts}"
  if attempts < 3
    raise "Not ready"
  end
  puts "Worked"
rescue
  retry
end

retry inside a method

The run_job method holds its rescue line with no begin line. The state hash counts the tries, and the guard stops retry once the count reaches 3.

def run_job(state)
  state[:tries] += 1
  puts "Try #{state[:tries]}"
  if state[:tries] < 2
    raise "Still warming up"
  end
  puts "Job done"
rescue
  if state[:tries] < 3
    retry
  end
  puts "Job gave up"
end
state = {tries: 0}
run_job(state)

ensure inside a method

The divide method rescues a zero division and returns 0 for it. The ensure line prints at the end of each call, success or failure.

def divide(a, b)
  a / b
rescue ZeroDivisionError
  puts "Divided by zero"
  0
ensure
  puts "Divide call over"
end
puts divide(10, 2)
puts divide(10, 0)

Example

attempts = 0
begin
  attempts += 1
  if attempts < 3
    raise "Server busy"
  end
  puts "Loaded on try #{attempts}"
rescue
  retry
ensure
  puts "Loading finished"
end

Key points

  • ensure runs after the begin part, error or no error.
  • ensure runs after a rescue line has handled an error.
  • retry sends control back to the start of the begin part.
  • A counter outside the block can count the tries across retries.
  • retry in a rescue line gives the block another run.
  • A method body acts as its own block, so rescue and retry can sit in a method with no begin line.

In this example, the block raises Server busy on the first two tries and the rescue line sends it back with retry. The counter reaches 3 on the third run, the block prints its loaded line, and ensure prints the closing line once at the very end.

Note

An unbounded retry loops forever, so every retry needs a stopping count.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A begin block raises an error, a rescue line handles it, and the block also has an ensure line. When does the ensure part run?