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.
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]