Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing multiple error classes to ruby's rescue clause in a DRY fashion

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.

like image 293
apb Avatar asked Apr 25 '11 18:04

apb


People also ask

How do I rescue two errors in Ruby?

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.

Can we use rescue without begin?

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 .

What is standard error in Ruby?

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.


1 Answers

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.


Splat Operator

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] 
like image 168
sawa Avatar answered Sep 21 '22 19:09

sawa