If you think an error condition may be transient or may be corrected (by the user, perhaps?), you can rerun all the code in a begin..end
block using the keyword retry
, as in this example that prompts the user to re-enter a value if an error such as ZeroDivisionError occurs:
retry.rb
def doCalc
begin
print( "Enter a number: " )
aNum = gets().chomp()
result = 100 / aNum.to_i
rescue Exception => e
result = 0
puts( "Error: " + e.to_s + "\nPlease try again." )
retry # retry on exception
else
msg = "Result = #{result}"
ensure
msg = "You entered '#{aNum}'. " + msg
end
return msg
end
When you want to append the message from an exception object such as e
to a string such as "Error: "
, Ruby 1.9 insists that you explicitly convert e
to a string ( "Error: " + e.to_s
), whereas Ruby 1.8 does the conversion for you ( "Error: " + e
).
There is, of course, the danger that the error may not be as transient as you think, so if you use retry
, you may want to provide a clearly defined exit condition to ensure that the code stops executing after a fixed number of attempts.
You could, for example, increment a local variable in the begin
clause. (If you do this, make sure it is incremented before any code that is liable to generate an exception since once an exception occurs, the remainder of the code prior to the rescue
clause will be skipped!) Then test the value of that variable in the rescue
section, like this:
rescue Exception => e if aValue < someValue then retry end
Here is a complete example, in which I test the value of a variable named tries
to ensure no more than three tries to run the code without error before the exception-handling block exits:
retry2.rb
def doCalc tries = 0 begin print( "Enter a number: " ) tries += 1 aNum = gets().chomp() result = 100 / aNum.to_i rescue Exception => e msg = "Error: " + e.to_s puts( msg ) puts( "tries = #{tries}" ) result = 0 if tries < 3 then # set a fixed number of retries retry end else msg = "Result = #{result}" ensure msg = "You entered '#{aNum}'. " + msg end return msg end
If the user were to enter 0 three times in a row, this would be the output:
Enter a number: 0 Error: divided by 0 tries = 1 Enter a number: 0 Error: divided by 0 tries = 2 Enter a number: 0 Error: divided by 0 tries = 3 You entered '0'. Error: divided by 0