Here's a snippet
def take_resource
puts "resource taken"
end
def free_resource source
puts "resource freed from #{source}"
end
def do_stuff
tries = 0
begin
take_resource
raise 'oops'
rescue
if tries < 3
tries += 1
free_resource 'rescue'
retry
end
raise
ensure
free_resource 'ensure'
end
end
do_stuff
# ~> -:13:in `do_stuff': oops (RuntimeError)
# ~> from -:28:in `<main>'
# >> resource taken
# >> resource freed from rescue
# >> resource taken
# >> resource freed from rescue
# >> resource taken
# >> resource freed from rescue
# >> resource taken
# >> resource freed from ensure
Here we see that ensure
clause is not invoked when we retry
the block. Why is that? Is there a logical explanation to this? I thought that ensure
is called ensure
for a reason: it always runs. Well, it turned out that I was wrong.
And while we're on it: do you know about other gotchas in this area (exception handling)?