What's the suggested raise Exception idiom?

What’s the distinction between:
raise ArgumentError, “the argument was invalid”
and
raise ArgumentError.new(“the argument was invalid”)

How does this apply in the case of exceptions with custom initializers
for attributes? For example:
class StatusCodeError < StandardError
attr_reader :status_code
def initialize(status_code)
@status_code = status_code
end
end

I’ve been reading a lot of code, books and blogs, but haven’t gotten
as clear of an understanding on why people choose one way over
another, so I’m looking for additional opinions and commentary.

Thanks

On 03/23/2010 06:22 PM, Nathan B. wrote:

      @status_code = status_code
  end

end

I’ve been reading a lot of code, books and blogs, but haven’t gotten
as clear of an understanding on why people choose one way over
another, so I’m looking for additional opinions and commentary.

I believe raise a,b,c,d… is merely syntactig sugar for raise
a.new(b,c,d…) with a bit of added functionality (e.g. if a is not an
exception class there is an error, if a is a String a StandardError is
raised).

To answer your question, normally there is no reason to use a variant
with “new” - rather save yourself a bit of typing and use the shorter
form. My 0.02EUR.

Kind regards

robert

On Mar 23, 2010, at 2:45 PM, Robert K. wrote:

 def initialize(status_code)

exception class there is an error, if a is a String a StandardError is
raised).

Not exactly so. According to the passage from RI below, “raise” with an
exception class as a first paremeter accepts up to 2 additional
parameters – the first one will be used as an argument to new when the
exception object is instantiated, and the second, if any, must be an
array representing callback information.

When I need an exception class with more than one argument, I use
something like the following:

class DimensionError < RuntimeError
attr_reader :width, :hight
def initialize(*args)
@width, @hight = *args
super “Wrong dimension #{width}x#{hight}”
end
end

begin
raise DimensionError, [ 5, 3 ]
rescue DimensionError => error
error.wigth
error.length
end

= OR =

class DimensionError < RuntimeError
attr_reader :width, :hight
def initialize(options = {})
@width = options[:width]
@hight = options[:hight]
super “Wrong dimension #{width}x#{hight}”
end
end

begin
raise DimensionError, :width => 5, :hight => 3
rescue DimensionError => error
error.wigth
error.length
end

----------------------------------------------------------- Kernel#raise
raise
raise(string)
raise(exception [, string [, array]])
fail
fail(string)
fail(exception [, string [, array]])

 With no arguments, raises the exception in $! or raises a
 RuntimeError if $! is nil. With a single String argument, raises a
 RuntimeError with the string as a message. Otherwise, the first
 parameter should be the name of an Exception class (or an object
 that returns an Exception object when sent an exception message).
 The optional second parameter sets the message associated with the
 exception, and the third parameter is an array of callback
 information. Exceptions are caught by the rescue clause of
 begin...end blocks.

    raise "Failed to create socket"
    raise ArgumentError, "No parameters", caller

2010/3/24 Gennady B. [email protected]:

On Mar 23, 2010, at 2:45 PM, Robert K. wrote:

I believe raise a,b,c,d… is merely syntactig sugar for raise
a.new(b,c,d…) with a bit of added functionality (e.g. if a is not an
exception class there is an error, if a is a String a StandardError is
raised).

Not exactly so. According to the passage from RI below, “raise” with an exception class as a first paremeter accepts up to 2 additional parameters – the first one will be used as an argument to new when the exception object is instantiated, and the second, if any, must be an array representing callback information.

Right you are. Thanks for the education! Apparently I never had the
need for this. :slight_smile:

begin
raise DimensionError, [ 5, 3 ]
rescue DimensionError => error
error.wigth
error.length
end

That does not seem to work as you expect on 1.9:

irb(main):038:0> class E1 < Exception
irb(main):039:1> def initialize(*a) p a end
irb(main):040:1> end
=> nil
irb(main):041:0> begin; raise E1,[1,2]; rescue Exception => e; p e; end
[[1, 2]]
#<E1: E1>
=> #<E1: E1>
irb(main):042:0> class E1 < Exception
irb(main):043:1> def initialize(*a) x,y=*a; p x,y end
irb(main):044:1> end
=> nil
irb(main):045:0> begin; raise E1,[1,2]; rescue Exception => e; p e; end
[1, 2]
nil
#<E1: E1>
=> #<E1: E1>
irb(main):046:0> RUBY_VERSION
=> “1.9.1”

You would have to do

irb(main):047:0> class E1 < Exception
irb(main):048:1> def initialize(a) x,y=*a; p x,y end
irb(main):049:1> end
=> nil
irb(main):050:0> begin; raise E1,[1,2]; rescue Exception => e; p e; end
1
2
#<E1: E1>
=> #<E1: E1>
irb(main):051:0>

Note the missing splash operator in initialize’s argument list.

Kind regards

robert

On Mar 24, 2010, at 1:31 AM, Robert K. wrote:

end

irb(main):044:1> end

Note the missing splash operator in initialize’s argument list.

Well, I am still on 1.8.6, missed the issue on 1.9.x ;-). Thanks for
pointing this out. Besides, an exception’s initialize() accepts only one
parameter anyway, so your no-splash version should work for 1.8.x as
well. I started using Hash-based initialize() recently, and it seems to
work same way both in 1.8 and 1.9.

Gennady.