Sometimes you may want to keep an exception “alive” even after it has been trapped in an exception-handling block. You can do this, for example, to defer the handling of the exception, say by passing it on to some other method. You can do this using the raise
method. You need to be aware, however, that, once raised, an exception needs to be rehandled; otherwise, it may cause your program to crash. Here is a simple example of raising a ZeroDivisionError exception and passing on the exception to a method called, in this case, handleError
:
raise.rb
begin divbyzero rescue Exception => e puts( "A problem just occurred. Please wait..." ) x = 0 begin raise rescue handleError( e ) end end
Here divbyzero
is the name of a method in which the divide-by-zero operation takes place, and handleError
is a method that prints more detailed information on the exception:
def handleError( e ) puts( "Error of type: #{e.class}" ) puts( e ) puts( "Here is a backtrace: " ) puts( e.backtrace ) end
Notice that this uses the backtrace
method, which displays an array of strings showing the filenames and line numbers where the error occurred and, in this case, the line that called the error-producing divbyzero
method. This is an example of this program’s output:
A problem just occurred. Please wait... Error of type: ZeroDivisionError divided by 0 Here is a backtrace: C:/Huw/programming/bookofruby/ch9/raise.rb:11:in `/' C:/Huw/programming/bookofruby/ch9/raise.rb:11:in `divbyzero' C:/Huw/programming/bookofruby/ch9/raise.rb:15:in `<main>'
You can also specifically raise your exceptions to force an error condition even when the program code has not caused an exception. Calling raise
on its own raises an exception of the type RuntimeError (or whatever exception is in the global variable $!
):
raise # raises RuntimeError
By default, this will have no descriptive message associated with it. You can add a message as a parameter, like this:
raise "An unknown exception just occurred!"
You can raise a specific type of error:
raise ZeroDivisionError
You can also create an object of a specific exception type and initialize it with a custom message:
raise ZeroDivisionError.new( "I'm afraid you divided by Zero" )
raise2.rb
begin raise ZeroDivisionError.new( "I'm afraid you divided by Zero" ) rescue Exception => e puts( e.class ) puts( "message: " + e.to_s ) end
This outputs the following:
ZeroDivisionError message: I'm afraid you divided by Zero
If the standard exception types don’t meet your requirements, you can, of course, create new ones just by subclassing existing exceptions. Provide your classes with a to_str
method in order to give them a default message.
raise3.rb
class NoNameError < Exception def to_str "No Name given!" end end
Here is an example of how you might raise a custom exception:
def sayHello( aName ) begin if (aName == "") or (aName == nil) then raise NoNameError end rescue Exception => e puts( e.class ) puts( "error message: " + e.to_s ) puts( e.backtrace ) else puts( "Hello #{aName}" ) end end
If you now enter sayHello( nil )
, this would be the output:
NoNameError error message: NoNameError C:/Huw/programming/bookofruby/ch9/raise3.rb:12:in `sayHello' C:/Huw/programming/bookofruby/ch9/raise3.rb:23:in `<main>'