module FiniteMachine::Catchable
A mixin to allow for specifying error handlers
Public Class Methods
included(base)
click to toggle source
Extends object with error handling methods
@api private
# File lib/finite_machine/catchable.rb, line 9 def self.included(base) base.module_eval do attr_threadsafe :error_handlers, default: [] end end
Public Instance Methods
catch_error(exception)
click to toggle source
Catches error and finds a handler
@param [Exception] exception
@return [Boolean]
true if handler is found, nil otherwise
@api public
# File lib/finite_machine/catchable.rb, line 50 def catch_error(exception) if handler = handler_for_error(exception) handler.arity.zero? ? handler.call : handler.call(exception) true end end
handle(*exceptions, &block)
click to toggle source
Rescue exception raised in state machine
@param [Array] exceptions
@example
handle TransitionError, with: :pretty_errors
@example
handle TransitionError do |exception| logger.info exception.message raise exception end
@api public
# File lib/finite_machine/catchable.rb, line 29 def handle(*exceptions, &block) options = exceptions.last.is_a?(Hash) ? exceptions.pop : {} unless options.key?(:with) if block_given? options[:with] = block else raise ArgumentError, "Need to provide error handler." end end evaluate_exceptions(exceptions, options) end
Private Instance Methods
evaluate_exceptions(exceptions, options)
click to toggle source
Check if exception inherits from Exception class and add to error handlers
@param [Array] exceptions
@param [Hash] options
@api private
# File lib/finite_machine/catchable.rb, line 102 def evaluate_exceptions(exceptions, options) exceptions.each do |exception| key = extract_exception_name(exception) error_handlers << [key, options[:with]] end end
evaluate_handler(handler)
click to toggle source
Executes given handler
@api private
# File lib/finite_machine/catchable.rb, line 82 def evaluate_handler(handler) case handler when Symbol target.method(handler) when Proc if handler.arity.zero? -> { instance_exec(&handler) } else ->(exception) { instance_exec(exception, &handler) } end end end
extract_const(class_name)
click to toggle source
Find constant in state machine namespace
@param [String] class_name
@api private
# File lib/finite_machine/catchable.rb, line 73 def extract_const(class_name) class_name.split("::").reduce(FiniteMachine) do |constant, part| constant.const_get(part) end end
extract_exception_name(exception)
click to toggle source
Extract exception name
@param [Class,Exception,String] exception
@api private
# File lib/finite_machine/catchable.rb, line 114 def extract_exception_name(exception) if exception.is_a?(Class) && exception <= Exception exception.name elsif exception.is_a?(String) exception else raise ArgumentError, "#{exception} isn't an Exception" end end
handler_for_error(exception)
click to toggle source
# File lib/finite_machine/catchable.rb, line 59 def handler_for_error(exception) _, handler = error_handlers.reverse.find do |class_name, _| klass = FiniteMachine.const_get(class_name) rescue nil klass ||= extract_const(class_name) exception <= klass end evaluate_handler(handler) end