0

I don't understand why this code is not working properly:

def test
  raise Exception.new 'error'
end

def caller
  begin
    test
  rescue =>e
     puts e.message
  end
end

caller

I want to catch the test exception in the caller method, but it seems that the caller method is not catching anything.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Ben D
  • 465
  • 1
  • 6
  • 20
  • fwiw, when performing a `begin rescue end` within a method, you can drop the `begin` and `end`. Saves a few lines of code i.e. `def caller;test;rescue Exception=>e;puts e.message;end` – stephenmurdoch Dec 31 '11 at 18:38
  • Just as a stylistic thing, you don't need to use `new` when raising an exception. `raise Exception, 'error'` is sufficient. – the Tin Man Dec 31 '11 at 18:45

3 Answers3

6

The reason your code doesn't work is because rescue without an explicitly stated exception type only catches StandardError, which is a subclass of Exception. Since you're raising Exception, which is higher than StandardError, your rescue doesn't catch it.

Generally you want to use more specific exceptions, and you almost never need to use Exception over StandardError.

This, for example, works fine:

begin
  raise StandardError.new 'Uh-oh!'
rescue => e
  p e.message
end

#=> Uh-oh!
coreyward
  • 77,547
  • 20
  • 137
  • 166
  • "Generally you want to use more specific exceptions", agreed. The added granularity helps when dealing with flow-control in "battle-conditions". – the Tin Man Dec 31 '11 at 18:47
2

You should specify what kind of exceptions you'd like to rescue. Try

  rescue Exception => e
Jan
  • 11,636
  • 38
  • 47
  • Thanks this worked well. I can't understand the difference between the throw and the raise statement... – Ben D Dec 31 '11 at 18:25
  • 1
    Not necessarily…see my answer. It's generally a bad idea to `rescue Exception => e` because you're probably catching lower-level exceptions than your application is ready to handle. – coreyward Dec 31 '11 at 18:26
  • @BenD, throw/raise differences [were covered in this question](http://stackoverflow.com/questions/51021/what-is-the-difference-between-raising-exceptions-vs-throwing-exceptions-in-ruby). – Jan Dec 31 '11 at 18:34
  • I agree with coreyward: The better advise is not to raise an `Exception` in the first place but using more specific error classes like `StandardError` – Niklas B. Dec 31 '11 at 18:38
1

Jan beat me to it, but...

When you use the => var syntax with exception, you must specify what kind of exception you want to rescue. The base class for all exceptions is Exception, so it will work if you change that to rescue Exception => e. Also, when what you're rescuing from is the entire body of a method, you don't need an explicit begin...end block...

def test
  raise Exception.new 'error'
end

def caller
  test
rescue Exception =>e
  puts e.message
end

caller()
Steve Jorgensen
  • 11,725
  • 1
  • 33
  • 43
  • Again, this is not necessarily true. You probably **don't** want to `rescue Exception => e` since you are going to catch lower-level exceptions than your program is able to deal with. – coreyward Dec 31 '11 at 18:29
  • 1
    Of course, I should have mentioned that rescuing `Exception` is not usually a good thing to do. Since, in this case, `Exception` is what is being raised, however, ... – Steve Jorgensen Dec 31 '11 at 18:37