module MSS::Core::LazyErrorClasses
Provides lazy creation of error classes via {#const_missing}.
Extend this module provides 3 benefits to another module:
-
A method that accepts strings and returns error classes.
-
Thread-safe dynamic error class creation via {#const_missing}
-
An error grammar for parsing
MSS
xml errors
Here is an example of how it works:
Class Foo module Errors extend MSS::Core::LazyErrorClasses end end Foo::Errors.error_class('NoSuchKey') #=> Foo::Errors::NoSuckKey Foo::Errors.error_class('Nested.Error.Klasses') #=> Foo::Errors::Nested::Error::Klasses
The errors returned from {#error_class} are subclasses of {MSS::Errors::Base}.
Constants
Public Class Methods
extended(base)
click to toggle source
@api private
# File lib/mss/core/lazy_error_classes.rb, line 53 def self.extended base unless base.const_defined?(:GRAMMAR) base.const_set(:GRAMMAR, BASE_ERROR_GRAMMAR) end mutex = Mutex.new MetaUtils.extend_method(base, :const_missing_mutex) { mutex } end
Public Instance Methods
const_missing(constant)
click to toggle source
Defines a new error class. @param [String,Symbol] constant @return [nil]
# File lib/mss/core/lazy_error_classes.rb, line 67 def const_missing constant const_missing_mutex.synchronize do # It's possible the constant was defined by another thread while # this thread was waiting on the mutex, check before setting. if error_const_set?(constant) const_get(constant) else const_set(constant, Class.new(Errors::Base) { extend LazyErrorClasses }) end end end
error_class(code)
click to toggle source
Converts the error code into an error class constant.
MSS::EC2::Errors.error_class('Non.Existent.Error') #=> MSS::EC2::Errors::Non::Existent::Error
@param [String] code An MSS
error code.
@return [Class] Returns the error class defiend by the error code.
# File lib/mss/core/lazy_error_classes.rb, line 88 def error_class code module_eval("#{self}::#{code.gsub('.Range','Range').gsub(".","::")}") end
Private Instance Methods
error_const_set?(constant)
click to toggle source
@return [Boolean] Returns true if the constant is defined in the
current module.
# File lib/mss/core/lazy_error_classes.rb, line 96 def error_const_set?(constant) # Not using #const_defined? because in Ruby 1.9+, it returns true for # constants not defined directly on the current module. constant = constant.to_sym # In Ruby 1.8, #constants returns an array of strings, # in Ruby 1.9+, #constants returns an array of symbols. constants.any? { |c| c.to_sym == constant } end