Module: IMW::Utils::DynamicallyExtendable::ClassMethods

Defined in:
lib/imw/utils/dynamically_extendable.rb

Overview

A collection of methods which provide a class including IMW::Utils::DynamicallyExtendable with a class-level Array of handlers that can be applied to instances by calling the instance’s extend_appropriately! method.

Instance Method Summary collapse

Instance Method Details

#extend_instance!(instance, options = {}) ⇒ Object

Iterate through this class’s handlers and extend the given object with modules whose handler conditions match the instance.

Passing in :use_modules or :skip_modules allows overriding the default behavior of handlers.

Parameters:

  • instance (Object)
  • options (Hash) (defaults to: {})

Options Hash (options):

  • use_modules (Array<String,Module>)

    a list of modules used regardless of handlers

  • skip_modules (Array<String,Module>)

    a list of modules not to be used regardless of handlers

Returns:

  • (Object)

    the newly extended object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/imw/utils/dynamically_extendable.rb', line 100

def extend_instance! instance, options={}
  return if options[:no_modules]
  options.reverse_merge!(:use_modules => [], :skip_modules => [])
  handlers.each do |mod_name, handler|
    case handler
    when Regexp    then extend_instance_with_mod_or_string!(instance, mod_name, options[:skip_modules]) if handler =~ instance.to_s
    when Proc      then extend_instance_with_mod_or_string!(instance, mod_name, options[:skip_modules]) if handler.call(instance)
    when TrueClass then extend_instance_with_mod_or_string!(instance, mod_name, options[:skip_modules])
    else           raise IMW::TypeError("A handler must be Regexp, Proc, or true")
    end
  end
  options[:use_modules].each { |mod_name| extend_instance_with_mod_or_string!(instance, mod_name, options[:skip_modules]) }
  instance
end

#extend_instance_with_mod_or_string!(instance, mod_or_string, skip_modules) ⇒ Object

Extend instance with mod_or_string. Will work hard to try and interpret mod_or_string as a module if it’s a string.

representing a module to extend the instance with

Parameters:

  • instance (Object)
  • mod_or_string (Module, String)

    the module or string

  • skip_modules (Array<Module,String>)

    modules to exclude



125
126
127
128
129
130
131
132
133
# File 'lib/imw/utils/dynamically_extendable.rb', line 125

def extend_instance_with_mod_or_string! instance, mod_or_string, skip_modules
  return if skip_modules.include?(mod_or_string)
  if mod_or_string.is_a?(Module)
    instance.extend(mod_or_string)
  else
    m = IMW.class_eval(mod_or_string)
    instance.extend(m) unless skip_modules.include?(m)
  end
end

#handlersArray<Array>

The handlers an including class has defined.

Returns:



51
52
53
# File 'lib/imw/utils/dynamically_extendable.rb', line 51

def handlers
  @handlers ||= []
end

#register_handler(mod, handler) ⇒ Object

Register a new handler for an including class.

handler must be one of

  1. Regexp

  2. Proc

  3. true

In case (1), if the regular expression matches the instance’s to_s method then the module (mod) will be used..

In case (2), if the Proc returns a value other than false or nil after being passed an instance then the module will be used.

In case (3), the module will be used.

Parameters:

  • mod (String, Module)
  • handler (Regexp, Proc, true)

Raises:



75
76
77
78
79
# File 'lib/imw/utils/dynamically_extendable.rb', line 75

def register_handler mod, handler
  raise IMW::ArgumentError.new("Module must be either a Module or String")       unless mod.is_a?(Module)     || mod.is_a?(String)
  raise IMW::ArgumentError.new("Handler must be either a Regexp, Proc, or true") unless handler.is_a?(Regexp) || handler.is_a?(Proc) || handler == true
  handlers << [mod, handler]
end

#register_handlers(*pairs) ⇒ Object

Register a collection of handlers.

See Also:



84
85
86
# File 'lib/imw/utils/dynamically_extendable.rb', line 84

def register_handlers *pairs
  pairs.each { |pair| register_handler *pair }
end