2012-12-17 06:26:15 +04:00
|
|
|
= Exception Handling
|
|
|
|
|
|
|
|
Exceptions are rescued in a +begin+/+end+ block:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# code that might raise
|
|
|
|
rescue
|
|
|
|
# handle exception
|
|
|
|
end
|
|
|
|
|
2015-12-18 06:39:49 +03:00
|
|
|
If you are inside a method, you do not need to use +begin+ or +end+ unless you
|
2012-12-17 06:26:15 +04:00
|
|
|
wish to limit the scope of rescued exceptions:
|
|
|
|
|
|
|
|
def my_method
|
|
|
|
# ...
|
|
|
|
rescue
|
|
|
|
# ...
|
|
|
|
end
|
|
|
|
|
2019-12-22 23:56:44 +03:00
|
|
|
The same is true for a +class+, +module+, and +block+:
|
2019-10-24 19:35:36 +03:00
|
|
|
|
|
|
|
[0, 1, 2].map do |i|
|
|
|
|
10 / i
|
|
|
|
rescue ZeroDivisionError
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
#=> [nil, 10, 5]
|
2012-12-17 06:26:15 +04:00
|
|
|
|
|
|
|
You can assign the exception to a local variable by using <tt>=>
|
|
|
|
variable_name</tt> at the end of the +rescue+ line:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# ...
|
|
|
|
rescue => exception
|
|
|
|
warn exception.message
|
|
|
|
raise # re-raise the current exception
|
|
|
|
end
|
|
|
|
|
2015-12-18 06:39:49 +03:00
|
|
|
By default, StandardError and its subclasses are rescued. You can rescue a
|
2012-12-17 06:26:15 +04:00
|
|
|
specific set of exception classes (and their subclasses) by listing them after
|
|
|
|
+rescue+:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# ...
|
|
|
|
rescue ArgumentError, NameError
|
|
|
|
# handle ArgumentError or NameError
|
|
|
|
end
|
|
|
|
|
|
|
|
You may rescue different types of exceptions in different ways:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# ...
|
|
|
|
rescue ArgumentError
|
|
|
|
# handle ArgumentError
|
|
|
|
rescue NameError
|
|
|
|
# handle NameError
|
|
|
|
rescue
|
|
|
|
# handle any StandardError
|
|
|
|
end
|
|
|
|
|
|
|
|
The exception is matched to the rescue section starting at the top, and matches
|
2015-12-18 06:39:49 +03:00
|
|
|
only once. If an ArgumentError is raised in the begin section, it will not be
|
2012-12-17 06:26:15 +04:00
|
|
|
handled in the StandardError section.
|
|
|
|
|
2013-01-15 22:06:24 +04:00
|
|
|
You may retry rescued exceptions:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# ...
|
|
|
|
rescue
|
|
|
|
# do something that may change the result of the begin block
|
|
|
|
retry
|
|
|
|
end
|
|
|
|
|
|
|
|
Execution will resume at the start of the begin block, so be careful not to
|
|
|
|
create an infinite loop.
|
|
|
|
|
|
|
|
Inside a rescue block is the only valid location for +retry+, all other uses
|
|
|
|
will raise a SyntaxError. If you wish to retry a block iteration use +redo+.
|
|
|
|
See {Control Expressions}[rdoc-ref:syntax/control_expressions.rdoc] for
|
|
|
|
details.
|
|
|
|
|
2012-12-17 06:26:15 +04:00
|
|
|
To always run some code whether an exception was raised or not, use +ensure+:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# ...
|
|
|
|
rescue
|
|
|
|
# ...
|
|
|
|
ensure
|
|
|
|
# this always runs
|
|
|
|
end
|
|
|
|
|
|
|
|
You may also run some code when an exception is not raised:
|
|
|
|
|
|
|
|
begin
|
|
|
|
# ...
|
|
|
|
rescue
|
|
|
|
# ...
|
|
|
|
else
|
|
|
|
# this runs only when no exception was raised
|
|
|
|
ensure
|
|
|
|
# ...
|
|
|
|
end
|