To add a collaborator to this project you will need to use the Relish gem to add the collaborator via a terminal command. Soon you'll be able to also add collaborators here!
More about adding a collaboratorexceptions
Signal exceptions using the
fail
method. Useraise
only when
catching an exception and re-raising it (because here you're not
failing, but explicitly and purposefully raising an exception).begin fail 'Oops' rescue => error raise if error.message != 'Oops' end
Don't specify
RuntimeError
explicitly in the two argument version offail/raise
.# bad fail RuntimeError, 'message' # good - signals a RuntimeError by default fail 'message'
Prefer supplying an exception class and a message as two separate
arguments tofail/raise
, instead of an exception instance.# bad fail SomeException.new('message') # Note that there is no way to do `fail SomeException.new('message'), backtrace`. # good fail SomeException, 'message' # Consistent with `fail SomeException, 'message', backtrace`.
Never return from an
ensure
block. If you explicitly return from a
method inside anensure
block, the return will take precedence over
any exception being raised, and the method will return as if no
exception had been raised at all. In effect, the exception will be
silently thrown away.def foo begin fail ensure return 'very bad idea' end end
Use implicit begin blocks where possible.
# bad def foo begin # main logic goes here rescue # failure handling goes here end end # good def foo # main logic goes here rescue # failure handling goes here end
Mitigate the proliferation of
begin
blocks by using
contingency methods (a term coined by Avdi Grimm).# bad begin something_that_might_fail rescue IOError # handle IOError end begin something_else_that_might_fail rescue IOError # handle IOError end # good def with_io_error_handling yield rescue IOError # handle IOError end with_io_error_handling { something_that_might_fail } with_io_error_handling { something_else_that_might_fail }
Don't suppress exceptions.
# bad begin # an exception occurs here rescue SomeError # the rescue clause does absolutely nothing end # bad do_something rescue nil
Avoid using
rescue
in its modifier form.# bad - this catches exceptions of StandardError class and its descendant classes read_file rescue handle_error($!) # good - this catches only the exceptions of Errno::ENOENT class and its descendant classes def foo read_file rescue Errno::ENOENT => ex handle_error(ex) end
Don't use exceptions for flow of control.
# bad begin n / d rescue ZeroDivisionError puts 'Cannot divide by 0!' end # good if d.zero? puts 'Cannot divide by 0!' else n / d end
Avoid rescuing the
Exception
class. This will trap signals and calls to
exit
, requiring you tokill -9
the process.# bad begin # calls to exit and kill signals will be caught (except kill -9) exit rescue Exception puts "you didn't really want to exit, right?" # exception handling end # good begin # a blind rescue rescues from StandardError, not Exception as many # programmers assume. rescue => e # exception handling end # also good begin # an exception occurs here rescue StandardError => e # exception handling end
Put more specific exceptions higher up the rescue chain, otherwise
they'll never be rescued from.# bad begin # some code rescue Exception => e # some handling rescue StandardError => e # some handling end # good begin # some code rescue StandardError => e # some handling rescue Exception => e # some handling end
Release external resources obtained by your program in an ensure block.
f = File.open('testfile') begin # .. process rescue # .. handle error ensure f.close unless f.nil? end
Favor the use of exceptions for the standard library over
introducing new exception classes.
Last published almost 7 years ago by David Kariuki.