Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

How do I implement default behavior for an Exception? begin rescue else doesn't work(which I think should).

And, isn't else meaningless in the scenario? Any code that has to run when no exception is raised does run between the begin-rescue block.

By the way I have the following workaround, but I'm not satisfied with it.

class MyException < Exception
end

class YourException < Exception
end

begin
  raise MyException if 2 > 50
  raise YourException if 1 < 90
rescue Exception => e
  case e.message
  when /MyException/
    puts "MyException Caught"
  else
    puts "Default Exception Caught"
  end
end
share|improve this question
    
Should have done the following: rescue MyException and then rescue Exception (Don't know why I didn't do that before. :( ) –  oozzal Jul 6 '13 at 13:34

2 Answers 2

up vote 3 down vote accepted

First of all, you really shouldn't subclass Exception. It is the superclass of all Ruby exceptions, including NoMemoryError, SyntaxError, Interrupt, SystemExit; all of which you don't normally need to rescue from. Doing so, whether accidentally or on purpose, is discouraged since it can prevent a program from exiting properly, even if it was interrupted by the user. It can also hide or produce some quite obscure bugs.

What you want to subclass is StandardError, which is the superclass of most Ruby errors we see in day-to-day programming. This class is also the one which will be rescued should you not specify one:

begin
  object.do_something!
rescue => error    # will rescue StandardError and all subclasses
  $stderr.puts error.message
end

I believe this is the "default behavior" you are looking for. You can handle a specific error, then all other errors in general:

class CustomApplicationError < StandardError
end

begin
  object.do_something!
rescue CustomApplicationError => error
  recover_from error
rescue => error
  log.error error.message
  raise
end

The else clause is not meaningless in error handling. It will execute the nested code if and only if no exceptions were raised, as opposed to the ensure clause which will execute code regardless. It allows you to handle success cases.

begin
  object.do_something!
rescue => error
  log.error error.message
else
  log.info 'Everything went smoothly'
end
share|improve this answer
    
The else clause didn't mean much to me, because I was stuck to figure how to handle default exception case. As soon as I got it, else was meaningful. Thanks for the response. :) –  oozzal Jul 8 '13 at 9:52
    
Figured out. Your second block of code is meaningful. Not to rescue "Exception" but just use rescue for other exceptions. Thanks :) –  oozzal Jul 23 '13 at 3:50

First, I do not understand why you are case-conditioning with the error message. Why not do it with the error itself by their class? Then, it would be like this:

begin
  raise MyException if 2 > 50
  raise YourException if 1 < 90
rescue Exception => e
  case e
  when MyException
    puts "MyException Caught"
  else
    puts "Default Exception Caught"
  end
end

Second, doing it as above is not the straightforward way. The correct way to do it is:

begin
  raise MyException if 2 > 50
  raise YourException if 1 < 90
rescue MyException
  puts "MyException Caught"
rescue Exception
  puts "Default Exception Caught"
end

If YourException were a subclass of StandardError, then it could be captured by rescue without specifying the exception class.

share|improve this answer
    
Yes, that's the right answer and I figured it out later (as mentioned in the comment). Thanks though. :) –  oozzal Jul 8 '13 at 9:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.