I have some code that needs to rescue multiple types of exceptions in ruby:
begin a = rand if a > 0.5 raise FooException else raise BarException end rescue FooException, BarException puts "rescued!" end
What I'd like to do is somehow store the list of exception types that I want to rescue somewhere and pass those types to the rescue clause:
EXCEPTIONS = [FooException, BarException]
and then:
rescue EXCEPTIONS
Is this even possible, and is it possible without some really hack-y calls to eval
? I'm not hopeful given that I'm seeing TypeError: class or module required for rescue clause
when I attempt the above.
Besides specifying a single exception class to rescue, you can pass an array of exception classes to the rescue keyword. This will allow you to respond to multiple errors in the same way. Multiple rescue blocks can be used to handle different errors in different ways.
The method definition itself does the work of begin , so you can omit it. You can also do this with blocks. Now, there is one more way to use the rescue keyword without begin .
StandardError is a superclass with many exception subclasses of its own, but like all errors, it descends from the Exception superclass. StandardErrors occur anytime a rescue clause catches an exception without an explicit Exception class specified.
You can use an array with the splat operator *
.
EXCEPTIONS = [FooException, BarException] begin a = rand if a > 0.5 raise FooException else raise BarException end rescue *EXCEPTIONS puts "rescued!" end
If you are going to use a constant for the array as above (with EXCEPTIONS
), note that you cannot define it within a definition, and also if you define it in some other class, you have to refer to it with its namespace. Actually, it does not have to be a constant.
The splat operator *
"unpacks" an array in its position so that
rescue *EXCEPTIONS
means the same as
rescue FooException, BarException
You can also use it within an array literal as
[BazException, *EXCEPTIONS, BangExcepion]
which is the same as
[BazException, FooException, BarException, BangExcepion]
or in an argument position
method(BazException, *EXCEPTIONS, BangExcepion)
which means
method(BazException, FooException, BarException, BangExcepion)
[]
expands to vacuity:
[a, *[], b] # => [a, b]
One difference between ruby 1.8 and ruby 1.9 is with nil
.
[a, *nil, b] # => [a, b] (ruby 1.9) [a, *nil, b] # => [a, nil, b] (ruby 1.8)
Be careful with objects on which to_a
is defined, as to_a
will be applied in such cases:
[a, *{k: :v}, b] # => [a, [:k, :v], b]
With other types of objects, it returns itself.
[1, *2, 3] # => [1, 2, 3]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With