Exceptions

  • Don’t use exceptions for flow of control.
    [link]

    1. # bad
    2. begin
    3. n / d
    4. rescue ZeroDivisionError
    5. puts "Cannot divide by 0!"
    6. end
    7. # good
    8. if d.zero?
    9. puts "Cannot divide by 0!"
    10. else
    11. n / d
    12. end
  • Avoid rescuing the Exception class.
    [link]

    1. # bad
    2. begin
    3. # an exception occurs here
    4. rescue Exception
    5. # exception handling
    6. end
    7. # good
    8. begin
    9. # an exception occurs here
    10. rescue StandardError
    11. # exception handling
    12. end
    13. # acceptable
    14. begin
    15. # an exception occurs here
    16. rescue
    17. # exception handling
    18. end
  • Don’t specify RuntimeError explicitly in
    the two argument version of raise. Prefer error sub-classes for clarity and
    explicit error creation.[link]

    1. # bad
    2. raise RuntimeError, 'message'
    3. # better - RuntimeError is implicit here
    4. raise 'message'
    5. # best
    6. class MyExplicitError < RuntimeError; end
    7. raise MyExplicitError

  • Prefer supplying an exception class and a message as two separate arguments
    to raise, instead of an exception instance.
    [link]

    1. # bad
    2. raise SomeException.new('message')
    3. # Note that there is no way to do `raise SomeException.new('message'), backtrace`.
    4. # good
    5. raise SomeException, 'message'
    6. # Consistent with `raise SomeException, 'message', backtrace`.
  • Avoid using rescue in its modifier form.
    [link]

    1. # bad
    2. read_file rescue handle_error($!)
    3. # good
    4. begin
    5. read_file
    6. rescue Errno:ENOENT => ex
    7. handle_error(ex)
    8. end