Friday, 30 January 2015

Ruby: Custom Errors for Lazy Bums with const_missing

Catching errors is quite a normal thing when writing code, every programing language has some variation of the throw/catch, in Ruby's case, it's the elegant begin, rescue and ensure blocks.
At some point in every project you stop catching "other" people's errors and start catching your own.
So you start creating you own error classes, there's a couple common approaches I've seen over the years.

  • Create an Errors namespace on each class/module you need and create errors for that there.
  • Create a generic Project::Errors with its own file bag and throw all errors in there.
I usually go for the second approach, so error classes don't distract me, but that's more of a personal preference anyway.
However, I am a lazy bum and I've got tired of specified my error classes, so I made this Gist as an example:
#The following two examples are equivalent
#Example 1, explicit error classe declaration
class MyMainNamespace
module Errors
class Error1 < StandardError; end
class Error2 < StandardError; end
end
end
#Example 2, use const_missing for maximum lazyness
class MyMainNamespace
module Errors
def self.const_missing class_name
self.const_set( class_name , Class.new( StandardError ) )
self.const_get( class_name )
end
end
end
#usage:
being
do_something
rescue MyMainNamespace::Errors::Error1
do_something_else
rescue MyMainNamespace::Errors::Error2
do_something_different
#only works with second example, throws an invalid constant Error404 otherwise
rescue MyMainNamespace::Errors::Error404
error_not_found
end
view raw errorclasses hosted with ❤ by GitHub


The main idea behind this, is letting you freely type your errors as you need them both where they're being raised and rescued and you don't need to worry about they existing since they'll be created in runtime for you.
This method is probably not very efficient, but I don't care for this case.