Ruby / Exception handling

From WhyNotWiki
Jump to: navigation, search


Exception handling  edit   (Category  edit)


Contents

Exception hierarchy

  • Exception
    • fatal
    • NoMemoryError
    • ScriptError
      • LoadError
      • NotImplementedError
      • SyntaxError
    • SignalException
      • Interrupt
    • StandardError
      • ArgumentError
      • IOError
        • EOFError
      • IndexError
      • LocalJumpError
      • NameError
        • NoMethodError
      • RangeError
        • FloatDomainError
      • RegexpError
      • RuntimeError
      • SecurityError
      • SystemCallError
        • Errorno::__ (ENOENT, etc.) (system-dependent)
      • ThreadError
      • TypeError
      • ZeroDivisionError
    • SystemExit
    • SystemStackError

The rescue statement modifier

Intro

rescue doesn't always have to be used with a begin block. You can do rescues even more concisely.

irb -> raise 'an error' rescue "Hey, there was an error!"
    => "Hey, there was an error!"

Or, most concisely of all:

irb -> raise 'an error' rescue nil
    => nil

It really doesn't get more concise than that for exception handling. If you just want to silence exceptions and you don't want to actually do any intelligent handling of them then rescue nil is your ticket.

Details

When you use rescue as a statement modifier, it rescues StandardError and its subclasses. You can't specify which class of exception(s) that you want to rescue like you can with the normal version of rescue (begin ... rescue Exception => exception ... end, for example).

You also can't do such things as "ensure" when you use this style of rescue.

Caveat: The thing you pass to rescue is what it should do when there's a StandardError -- not the class of exceptions that it should rescue

That fact is a bit confusing, because it's different from the normal begin/rescue blocks.

irb -> begin
         raise "A runtime error"
       rescue RuntimeError
         "The thing that I want to happen when there's a RuntimeError"
       end
    => "The thing that I want to happen when there's a RuntimeError"

but:

irb -> raise "A runtime error" rescue "The thing that I want to happen when there's a RuntimeError"
    => "The thing that I want to happen when there's a RuntimeError"

If you forget this fact, you may be surprised when the error class itself is returned:

irb -> raise "A runtime error" rescue TypeError
    => TypeError

As soon as the error is rescued and you're no longer in the rescue block, $ERROR_INFO/$! resets to nil.

irb -> require 'English'
    => true

irb -> $ERROR_INFO
    => nil

irb -> raise "A runtime error" rescue puts $ERROR_INFO.inspect
#<RuntimeError: A runtime error>
    => nil

irb -> $ERROR_INFO
    => nil
irb -> $!
    => nil

Example: print errors without stopping

Use this trick when you want to see error messages that are raised but you want execution to continue:

irb -> NotARealClass.new() rescue $stderr.puts $!.inspect
#<NameError: uninitialized constant NotARealClass>
    => nil

or just:

irb -> NotARealClass.new() rescue $stderr.puts $!
uninitialized constant NotARealClass
    => nil

http://codeforpeople.com/lib/ruby/autorequire/autorequire-0.0.0/README

    # rescues error and prints its message- support method for samples/*
    #
    def print_error
      yield
    rescue Exception => e
      puts "#{ e } (#{ e.class })!"
    end

Like all things in Ruby, rescue has a return value

This can be useful, for example, when you need to assign a default value to a variable if an error occurs.

irb -> an_important_variable = SomethingThatWillRaiseAnError.do_calculation rescue "a sane default value"
    => "a sane default value"

You may be thinking (if you come from a background in other, less orthogonal languages), how can you do things like rescue puts $!.inspect? You can do that because puts, like all methods and blocks, has a return value.

irb -> a = puts "whatever"
whatever
    => nil

irb -> puts a
nil
    => nil

irb -> a = raise 'arg!' rescue puts 'whatever'
whatever
    => nil

irb -> puts a
nil
    => nil

Can have an ensure without a begin block

def something_that_might_raise_an_error
  raise "an error"
ensure
  puts "that we print this no matter what"
end

something_that_might_raise_an_error rescue puts $!
that we print this no matter what
an error
Ads
Personal tools