Class: Object
- Inherits:
- BasicObject
- Defined in:
- lib/add_hook.rb
Instance Method Summary collapse
-
#add_hook(method_name, &block) ⇒ Object
Add as a callback to an instance method.
Instance Method Details
#add_hook(method_name, &block) ⇒ Object
Add as a callback to an instance method
Usage
>> x = [1, 2]
=> [1, 2]
>> x.add_hook(:<<){|the_array, *args| puts "called #{ the_array.inspect } << #{ args.inspect }" }
=> nil
>> x << 'foo'
called [1, 2] << ["foo"]
=> [1, 2, "foo"]
Parameters
- method_name<~to_s>
-
The name of the method to add a hook to
- &block
-
A block to run everytime the method gets called. The block is passed multiple arguments. The first argument is self, the instance that the method is being called on. The rest of the arguments are the arguments that were passed to the method.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/add_hook.rb', line 25 def add_hook method_name, &block # protect against infinite looping return if method_name.to_s == 'add_hook' # if we haven't hooked into any methods on this instance yet # then we need to add a way to persist our hooked methods and callbacks unless self.respond_to? :hooked_methods # add some things to this particular object class << self attr_accessor :hooked_methods, :hooked_method_hooks end # initalize attributes self.hooked_methods ||= { } self.hooked_method_hooks ||= { } end # for now, assume this is an *instance method* that we're hooking method = self.class.instance_method(method_name.to_s) method_key = method_name.to_s + Time.now.to_s if method self.hooked_methods[ method_key ] = method # store the original method self.hooked_method_hooks[ method_key ] = block # store the block to call # using eval because define_method can't create # a method that accepts a block eval %{ def self.#{ method_name } *args #, &block self.hooked_method_hooks[#{ method_key.inspect }].call(self, *args) self.hooked_methods[#{ method_key.inspect }].bind(self).call(*args) # add block end } else raise "Cannot find method #{ method_name.inspect } to add hook to" end end |