class MethodObserver
def self.instances
def self.instances @instances ||= {} end
def self.new(*args)
def self.new(*args) o = super instances[o.object_id] = o o end
def make_observable(target)
def make_observable(target) methods_to_observe.each do |method| target.instance_eval %{ def #{method}(*args, &block) observer = #{self.class}.instances[#{object_id}] observer.send(:before_#{method}, *args, &block) if observer.respond_to? :before_#{method} observer.result = super observer.send(:after_#{method}, *args, &block) if observer.respond_to? :after_#{method} observer.result end } end end
def methods_for(name)
def methods_for(name) methods.grep(/^#{name}_/).map { |n| n.to_s.gsub(/^#{name}_/, '').intern } end
def methods_to_observe
def methods_to_observe (methods_for(:before) + methods_for(:after)).uniq end
def observe(target)
def observe(target) raise ObserverCannotObserveTwiceError if @target @target = target make_observable(target) end