what's the suggested raise Exception idiom?

N

Nathan Beyer

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
 
R

Robert Klemme

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.

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
 
G

Gennady Bystritsky

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

Not exactly so. According to the passage from RI below, "raise" with an exc=
eption 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 call=
back 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 =3D *args
super "Wrong dimension #{width}x#{hight}"
end
end

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

=3D OR =3D

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

begin
raise DimensionError, :width =3D> 5, :hight =3D> 3
rescue DimensionError =3D> 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=20
RuntimeError if $! is nil. With a single String argument, raises a=20
RuntimeError with the string as a message. Otherwise, the first=20
parameter should be the name of an Exception class (or an object=20
that returns an Exception object when sent an exception message).=20
The optional second parameter sets the message associated with the=20
exception, and the third parameter is an array of callback=20
information. Exceptions are caught by the rescue clause of=20
begin...end blocks.

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

Robert Klemme

2010/3/24 Gennady Bystritsky said:
On Mar 23, 2010, at 2:45 PM, Robert Klemme wrote:

Not exactly so. According to the passage from RI below, "raise" with an e=
xception 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 objec=
t is instantiated, and the second, if any, must be an array representing ca=
llback information.

Right you are. Thanks for the education! Apparently I never had the
need for this. :)
When I need an exception class with more than one argument, I use somethi= ng like the following:

class DimensionError < RuntimeError
=A0attr_reader :width, :hight
=A0def initialize(*args)
=A0 =A0@width, @hight =3D *args
=A0 =A0super "Wrong dimension #{width}x#{hight}"
=A0end
end

begin
=A0raise DimensionError, [ 5, 3 ]
rescue DimensionError =3D> error
=A0error.wigth
=A0error.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
=3D> nil
irb(main):041:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
[[1, 2]]
#<E1: E1>
=3D> #<E1: E1>
irb(main):042:0> class E1 < Exception
irb(main):043:1> def initialize(*a) x,y=3D*a; p x,y end
irb(main):044:1> end
=3D> nil
irb(main):045:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
[1, 2]
nil
#<E1: E1>
=3D> #<E1: E1>
irb(main):046:0> RUBY_VERSION
=3D> "1.9.1"

You would have to do

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

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

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
G

Gennady Bystritsky

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 obje=
ct is instantiated, and the second, if any, must be an array representing c=
allback information.
=20
Right you are. Thanks for the education! Apparently I never had the
need for this. :)
=20
When I need an exception class with more than one argument, I use someth= ing like the following:
=20
class DimensionError < RuntimeError
attr_reader :width, :hight
def initialize(*args)
@width, @hight =3D *args
super "Wrong dimension #{width}x#{hight}"
end
end
=20
begin
raise DimensionError, [ 5, 3 ]
rescue DimensionError =3D> error
error.wigth
error.length
end
=20
That does not seem to work as you expect on 1.9:
=20
irb(main):038:0> class E1 < Exception
irb(main):039:1> def initialize(*a) p a end
irb(main):040:1> end
=3D> nil
irb(main):041:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
[[1, 2]]
#<E1: E1>
=3D> #<E1: E1>
irb(main):042:0> class E1 < Exception
irb(main):043:1> def initialize(*a) x,y=3D*a; p x,y end
irb(main):044:1> end
=3D> nil
irb(main):045:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
[1, 2]
nil
#<E1: E1>
=3D> #<E1: E1>
irb(main):046:0> RUBY_VERSION
=3D> "1.9.1"
=20
You would have to do
=20
irb(main):047:0> class E1 < Exception
irb(main):048:1> def initialize(a) x,y=3D*a; p x,y end
irb(main):049:1> end
=3D> nil
irb(main):050:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
1
2
#<E1: E1>
=3D> #<E1: E1>
irb(main):051:0>
=20
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 pointi=
ng this out. Besides, an exception's initialize() accepts only one paramete=
r anyway, so your no-splash version should work for 1.8.x as well. I starte=
d using Hash-based initialize() recently, and it seems to work same way bot=
h in 1.8 and 1.9.

Gennady.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top