Skip to content

Instantly share code, notes, and snippets.

@timuruski
Last active December 20, 2015 05:59
Show Gist options
  • Select an option

  • Save timuruski/6081990 to your computer and use it in GitHub Desktop.

Select an option

Save timuruski/6081990 to your computer and use it in GitHub Desktop.
require 'active_support/core_ext/array/extract_options'
# This makes it easy to tag all errors generated by the app with the
# CustomError module so they can be handled specifically. The NestedException
# module is also included so that it can wrap errors from other parts
# of the system.
module CustomError
# Public: Builds a new Error class and optionally includes the
# NestedException module.
#
# Usage:
# MyError = CustomError.new do
# def message
# 'custom message'
# end
# end
#
# # This inherits from StandardError instead of RuntimeError
# AnotherError = CustomError.new(StandardError, :nested => true)
#
def self.new(*args, &block)
options = args.extract_options!
base = args.first || RuntimeError
mixins = [self]
mixins << NestedException if options.fetch(:nested, false)
Class.new(base, &block).class_exec { include *mixins }
end
end
# Adapted from from: http://nestegg.rubyforge.org/
module NestedException
# Public: Initializes a new nested error, the original error defaults
# to the global error variable so that it doesn't need to be explicity
# provided when re-raising an exception.
def initialize(message = nil, cause = $!)
@cause = cause
super(message || cause && cause.message)
end
attr_reader :cause
def set_backtrace(new_backtrace)
if cause
last_line = new_backtrace.last
cause_lines = cause.backtrace
.take_while { |line| line != last_line }
new_backtrace << "cause: #{cause.class.name}: #{cause}"
new_backtrace.concat(cause_lines)
end
super(new_backtrace)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment