Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Custom Exceptions

Reply
Thread Tools

Custom Exceptions

 
 
Leslie Viljoen
Guest
Posts: n/a
 
      04-06-2010
[Note: parts of this message were removed to make it a legal post.]

Hi everyone

I want to make a custom exception like so:

class BillRowError < StandardError
def initialize(field, index)
@field = field
@index = index
end
end

I'll call this like so:
raise(BillRowError.new(:roamingcalls, @index), "Roaming Calls field
missing") if n.length == 0

But now I'd like to be able to modify the string that Ruby prints when the
exception is not rescue'd. I thought I could add this method to the
BillRowError class:

def message
@message + " field: #{@field}, row: #{@index}"
end

That almost works but I get a "instance variable @message not initialized"
warning, which means Ruby is not setting @message in my object like I
expected. Making my own message= method doesn't help.

Can an exception object access and modify the message that gets passed in
the "raise"?

 
Reply With Quote
 
 
 
 
Chris Hulan
Guest
Posts: n/a
 
      04-06-2010
On Apr 6, 10:44*am, Leslie Viljoen <(E-Mail Removed)> wrote:
> [Note: *parts of this message were removed to make it a legal post.]
>
> Hi everyone
>
> I want to make a custom exception like so:
>
> class BillRowError < StandardError
> * * def initialize(field, index)
> * * * * @field = field
> * * * * @index = index
> * * end
> end
>
> I'll call this like so:
> raise(BillRowError.new(:roamingcalls, @index), "Roaming Calls field
> missing") if n.length == 0
>
> But now I'd like to be able to modify the string that Ruby prints when the
> exception is not rescue'd. I thought I could add this method to the
> BillRowError class:
>
> * * def message
> * * * * @message + " field: #{@field}, row: #{@index}"
> * * end
>
> That almost works but I get a "instance variable @message not initialized"
> warning, which means Ruby is not setting @message in my object like I
> expected. Making my own message= method doesn't help.
>
> Can an exception object access and modify the message that gets passed in
> the "raise"?


The default Exception:initialize is defined to take 1 parameter, a
string containing the error message
You define different initialize parameters so @message is not getting
set as expected

Maybe something like:
class BillRowError < StandardError
def initialize(msg, field, index)
super(msg)
@field = field
@index = index
end

def message
@message + " field: #{@field}, row: #{@index}"
end

end
....
raise(BillRowError.new("Roaming Calls field missing",:roamingcalls,
@index), ) if n.length == 0

cheers
 
Reply With Quote
 
 
 
 
Mario Antonetti
Guest
Posts: n/a
 
      04-06-2010
[Note: parts of this message were removed to make it a legal post.]

On Tue, Apr 6, 2010 at 9:44 AM, Leslie Viljoen <(E-Mail Removed)>wrote:

> Hi everyone
>
> I want to make a custom exception like so:
>
> class BillRowError < StandardError
> def initialize(field, index)
> @field = field
> @index = index
> end
> end
>
> I'll call this like so:
> raise(BillRowError.new(:roamingcalls, @index), "Roaming Calls field
> missing") if n.length == 0
>
> But now I'd like to be able to modify the string that Ruby prints when the
> exception is not rescue'd. I thought I could add this method to the
> BillRowError class:
>
> def message
> @message + " field: #{@field}, row: #{@index}"
> end
>
> That almost works but I get a "instance variable @message not initialized"
> warning, which means Ruby is not setting @message in my object like I
> expected. Making my own message= method doesn't help.
>
> Can an exception object access and modify the message that gets passed in
> the "raise"?
>


You could try rewriting the to_s method and take advantage of the
inheritance:

def to_s
super + " field: #{@field}, row: #{@index}"
end

That worked for me. I'm not sure if this is the recommended solution.

 
Reply With Quote
 
Brian Candler
Guest
Posts: n/a
 
      04-06-2010
Judging by the C source, Exception uses hidden(*) instance variables
"mesg" and "bt" for message and backtrace respectively. However, the
accessor #message internally calls #to_s, which you can override.

class BillRowError < StandardError
def initialize(field, index)
@field = field
@index = index
end

alias rig_to_s :to_s
def to_s
"#{orig_to_s} field: #{@field}, row: #{@index}"
end
end

begin
raise BillRowError.new(5, 7), "bar"
rescue BillRowError => e
p e
p e.instance_variables
p e.message
p e.backtrace
end

Produces:

#<BillRowError: bar field: 5, row: 7>
["@index", "@field"]
"bar field: 5, row: 7"
["ert.rb:14"]

Admittedly this behaviour doesn't seem to be well documented, so may be
fragile. Use at your own risk.

HTH,

Brian.

(*) It uses instance variables whose names don't begin with '@' and so
cannot be accessed by normal code
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Brian Candler
Guest
Posts: n/a
 
      04-06-2010
Chris Hulan wrote:
> The default Exception:initialize is defined to take 1 parameter, a
> string containing the error message


But 'raise' also lets you pass an error message, in addition to the
exception instance.

Note that even the default constructor doesn't create an instance
variable called @message.

class Foo < StandardError
end

begin
raise Foo, "bar"
rescue Foo => e
p e
p e.instance_variables
p e.instance_variable_get(:@message)
p e.message
p e.backtrace
end

#<Foo: bar>
[] # << No instance variables!
nil # << No @message!
"bar"
["ert.rb:5"]
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Chris Hulan
Guest
Posts: n/a
 
      04-06-2010
On Apr 6, 11:56*am, Brian Candler <(E-Mail Removed)> wrote:
> Chris Hulan wrote:
> > The default Exception:initialize is defined to take 1 parameter, a
> > string containing the error message

>
> But 'raise' also lets you pass an error message, in addition to the
> exception instance.
>
> Note that even the default constructor doesn't create an instance
> variable called @message.
>
> class Foo < StandardError
> end
>
> begin
> * raise Foo, "bar"
> rescue Foo => e
> * p e
> * p e.instance_variables
> * p e.instance_variable_get(:@message)
> * p e.message
> * p e.backtrace
> end
>
> #<Foo: bar>
> [] * * * * * * *# << No instance variables!
> nil * * * * * * # << No @message!
> "bar"
> ["ert.rb:5"]
> --
> Posted viahttp://www.ruby-forum.com/.


I should stop answering questions based on reading the docs at ruby-
docs.org, they are just not very clear...plus sloppy reading on my
part doesn't help
So message is not an attribute so using @message is wrong.
It looks like overriding to_s, or maybe using super in the override of
message to get the parents input.

cheers
 
Reply With Quote
 
Leslie Viljoen
Guest
Posts: n/a
 
      04-06-2010
[Note: parts of this message were removed to make it a legal post.]

On Tue, Apr 6, 2010 at 7:10 PM, Chris Hulan <(E-Mail Removed)> wrote:

>
> I should stop answering questions based on reading the docs at ruby-
> docs.org, they are just not very clear...plus sloppy reading on my
> part doesn't help
> So message is not an attribute so using @message is wrong.
> It looks like overriding to_s, or maybe using super in the override of
> message to get the parents input.
>
>

Yip, these surprising revelations were the reason for my post!

 
Reply With Quote
 
Leslie Viljoen
Guest
Posts: n/a
 
      04-06-2010
[Note: parts of this message were removed to make it a legal post.]

On Tue, Apr 6, 2010 at 5:24 PM, Brian Candler <(E-Mail Removed)> wrote:

> Judging by the C source, Exception uses hidden(*) instance variables
> "mesg" and "bt" for message and backtrace respectively. However, the
> accessor #message internally calls #to_s, which you can override.
>
> class BillRowError < StandardError
> def initialize(field, index)
> @field = field
> @index = index
> end
>
> alias rig_to_s :to_s
> def to_s
> "#{orig_to_s} field: #{@field}, row: #{@index}"
> end
> end
>
> begin
> raise BillRowError.new(5, 7), "bar"
> rescue BillRowError => e
> p e
> p e.instance_variables
> p e.message
> p e.backtrace
> end
>
> Produces:
>
> #<BillRowError: bar field: 5, row: 7>
> ["@index", "@field"]
> "bar field: 5, row: 7"
> ["ert.rb:14"]
>
> Admittedly this behaviour doesn't seem to be well documented, so may be
> fragile. Use at your own risk.
>
>

Wow thanks for this, I didn't think of aliasing the old to_s. I find it
strange that exceptions don't just use a plain old @message instance
variable but I suppose there's some good reason for it.


--
Do not support Microsoft:
http://www.vanwensveen.nl/rants/microsoft/IhateMS.html

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Exceptions - How do you make it work like built-in exceptions? Lie Python 3 01-14-2008 06:45 PM
Exceptions + Performance on path without exceptions gratch06@gmail.com C++ 3 04-16-2007 08:52 PM
Checked exceptions vs unchecked exceptions Ahmed Moustafa Java 5 07-14-2004 01:46 PM
Custom Exceptions with Web Services Chris Dunaway ASP .Net 1 01-13-2004 10:35 PM
Custom exceptions -- inherit from exceptions.Exception? Paul Miller Python 3 11-12-2003 09:24 AM



Advertisments