41

In ruby to catch an error one uses the rescue statement. generally this statement occurs between begin and end. One can also use a rescue statement as part of a block (do ... end) or a method (def ... end). My question is what other structures (loop, while, if, ...) if any will rescue nest within?

John F. Miller
  • 26,961
  • 10
  • 71
  • 121
  • `do ... end` blocks can't be rescued from without an explicit `begin ... end`. – Nick Feb 24 '17 at 21:55
  • 1
    Since [ruby 2.5](https://github.com/ruby/ruby/commit/0ec889d7ed) `do ... end` blocks can be rescued without an explicit `begin ... end`. – pimpin Jan 05 '21 at 12:02

2 Answers2

50

You can only use rescue in two cases:

  • Within a begin ... end block

    begin
      raise
    rescue 
      nil
    end
    
  • As a statement modifier

    i = raise rescue nil
    

Function, module, and class bodies (thanks Jörg) are implicit begin...end blocks, so you can rescue within any function without an explicit begin/end.

    def foo
      raise
    rescue
      nil
    end

The block form takes an optional list of parameters, specifying which exceptions (and descendants) to rescue:

    begin
      eval string
    rescue SyntaxError, NameError => boom
      print "String doesn't compile: " + boom
    rescue StandardError => bang
      print "Error running script: " + bang
    end

If called inline as a statement modifier, or without argument within a begin/end block, rescue will catch StandardError and its descendants.

Here's the 1.9 documentation on rescue.

klochner
  • 8,077
  • 1
  • 33
  • 45
  • 4
    `module` and `class` bodies are implicit `begin` blocks, too. – Jörg W Mittag Mar 26 '10 at 18:01
  • 4
    @Jörg W Mittag: as are `do ... end` blocks and `def ... end` method definitions. IS there anything else that is an implicit `begin`? `while`, `case`, or `if` for example? – John F. Miller Mar 28 '10 at 01:24
  • 7
    @john - do...end isn't an implicit begin...end. – klochner Mar 28 '10 at 02:20
  • I suggest adding the comment above about do...end to the answer... that is really what I was looking for. – pedz Jul 26 '17 at 15:51
  • 6
    Although not very well documented, as of ruby 2.5 `rescue` works in regular `do`/`end` blocks (not in-line blocks `{...}` though). [commit](https://github.com/ruby/ruby/commit/0ec889d7ed) – Vigintas Labakojis Feb 18 '20 at 15:38
11

As said in recent comment, response has changed since Ruby 2.5.

do ... end blocks are now implicit begin ... end blocks; like module, class and method bodies.

In-line blocks {...} still can't.

pimpin
  • 277
  • 2
  • 13