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