Module: Interloper::ClassMethods
- Defined in:
- lib/interloper.rb
Instance Method Summary collapse
- #after(*method_names, &callback) ⇒ Object
-
#ancestor_interloper_module ⇒ Module
The nearest ancstors tha is an interloper module.
- #before(*method_names, &callback) ⇒ Object
- #generate_interloper_module ⇒ Object
- #inherit_callbacks_after(*method_names) ⇒ Object
- #inherit_callbacks_before(*method_names) ⇒ Object
- #inherit_callbacks_for(*method_names) ⇒ Object
- #inherited_callbacks(hook, *method_names) ⇒ Object
- #interloper_const_name ⇒ Object
-
#interloper_module ⇒ Object
Generates an Interloper module that is namespaced under the including class, if one does not already exist.
-
#prepended?(const_name) ⇒ Boolean
Boolean True if the interloper module has already been prepnded;] false otherwise.
- #prepended_modules ⇒ Object
Instance Method Details
#after(*method_names, &callback) ⇒ Object
131 132 133 134 |
# File 'lib/interloper.rb', line 131 def after(*method_names, &callback) interloper_module.define_interloper_methods(*method_names, interloper_const_name) interloper_module.add_callbacks(:after, *method_names, &callback) end |
#ancestor_interloper_module ⇒ Module
Returns The nearest ancstors tha is an interloper module.
160 161 162 163 164 |
# File 'lib/interloper.rb', line 160 def ancestor_interloper_module ancestors.detect do |ancestor| ancestor.respond_to?(:interloper_module) && (ancestor != self) end.interloper_module end |
#before(*method_names, &callback) ⇒ Object
126 127 128 129 |
# File 'lib/interloper.rb', line 126 def before(*method_names, &callback) interloper_module.define_interloper_methods(*method_names, interloper_const_name) interloper_module.add_callbacks(:before, *method_names, &callback) end |
#generate_interloper_module ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/interloper.rb', line 54 def generate_interloper_module Module.new do class << self # @return [Array] The list of available hooks. def hooks [:before, :after] end # @return [Hash] The default hash for tracking callbacks to methods. def default_callbacks {}.tap do |callbacks| hooks.each do |hook| callbacks[hook] = {} end end end # @param [Symbol] hook Optional name of a hook. See .hook method in # this module. # @param [Symbol] method_name Optional name of a method. # @return [Hash, Array] A hash or array of callbacks. If the 'hook' # param is provided, it will return a hash of callbacks keyed by # method name. If both 'hook' and 'method_name' are provided, will # return an array of callbacks for the given hook and method. def callbacks(hook=nil, method_name=nil) @callbacks ||= default_callbacks if hook && method_name # Returns callback stack for a given method and hook. If there # aren't callbacks in the stack, return something enumberable to # be loop-friendly. @callbacks.fetch(hook).fetch(method_name, []) elsif hook # Return all callbacks for a given hook, e.g. :before. @callbacks.fetch(hook) else @callbacks end end def run_callbacks(hook, method_name, object_context, *orig_args, &orig_block) callbacks(hook, method_name).each do |callback| object_context.instance_exec *orig_args, &callback end end def add_callbacks(hook, *method_names, &callback) method_names.each do |method_name| callbacks[hook][method_name] ||= [] callbacks[hook][method_name] << callback end end def define_interloper_methods(*method_names, interloper_module_name) method_names.each do |method_name| unless instance_methods.include? method_name module_eval do eval <<-CODE def #{method_name}(*args, &block) self.class.const_get(:#{interloper_module_name}).run_callbacks(:before, :#{method_name}, self, *args, &block) return_val = super(*args, &block) self.class.const_get(:#{interloper_module_name}).run_callbacks(:after, :#{method_name}, self, *args, &block) return_val end CODE end end end end end end end |
#inherit_callbacks_after(*method_names) ⇒ Object
147 148 149 150 151 |
# File 'lib/interloper.rb', line 147 def inherit_callbacks_after(*method_names) inherited_callbacks(:after, *method_names).each do |callback| after(*method_names, &callback) end end |
#inherit_callbacks_before(*method_names) ⇒ Object
141 142 143 144 145 |
# File 'lib/interloper.rb', line 141 def inherit_callbacks_before(*method_names) inherited_callbacks(:before, *method_names).each do |callback| before(*method_names, &callback) end end |
#inherit_callbacks_for(*method_names) ⇒ Object
136 137 138 139 |
# File 'lib/interloper.rb', line 136 def inherit_callbacks_for(*method_names) inherit_callbacks_before(*method_names) inherit_callbacks_after(*method_names) end |
#inherited_callbacks(hook, *method_names) ⇒ Object
153 154 155 156 157 |
# File 'lib/interloper.rb', line 153 def inherited_callbacks(hook, *method_names) method_names.map do |method_name| ancestor_interloper_module.callbacks[hook][method_name] end.flatten end |
#interloper_const_name ⇒ Object
15 16 17 18 19 20 21 |
# File 'lib/interloper.rb', line 15 def interloper_const_name if self.name "Interloper" else "AnonymousInterloper#{self.object_id}" end.to_sym end |
#interloper_module ⇒ Object
Generates an Interloper module that is namespaced under the including class, if one does not already exist. Then prepends the Interloper module to the including class.
28 29 30 31 32 33 34 |
# File 'lib/interloper.rb', line 28 def interloper_module unless prepended? interloper_const_name const_set(interloper_const_name, generate_interloper_module) prepend const_get(interloper_const_name) end const_get(interloper_const_name) end |
#prepended?(const_name) ⇒ Boolean
Returns Boolean True if the interloper module has already been prepnded;] false otherwise.
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/interloper.rb', line 38 def prepended?(const_name) if self.name # If we are not anonymous, then check for the interloper constant name # in the list of prepended modules. prepended_modules.include? const_name else # If we are an anonymous class, check for the anonymous interloper # module name in the list of constants defined for this class. self.constants.include? interloper_const_name end end |
#prepended_modules ⇒ Object
50 51 52 |
# File 'lib/interloper.rb', line 50 def prepended_modules ancestors.slice(0, ancestors.find_index(self)) end |