Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
566 views
in Technique[技术] by (71.8m points)

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...