File: lib/method_observer.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  class: MethodObserver#1
inherits from
  Object ( Builtin-Module )
has properties
attribute: target [R] #3
attribute: result [RW] #4
method: observe / 1 #12
class method: instances #18
class method: new / 1 #22
method: make_observable / 1 #29
method: methods_to_observe #43
method: methods_for / 1 #47
  class: ObserverCannotObserveTwiceError#6
inherits from
  StandardError ( Builtin-Module )
has properties
method: initialize / 1 #7

Code

   1  class MethodObserver
   2    
   3    attr_reader :target
   4    attr_accessor :result
   5    
   6    class ObserverCannotObserveTwiceError < StandardError
   7      def initialize(message = 'observer cannot observe twice')
   8        super
   9      end
  10    end
  11    
  12    def observe(target)
  13      raise ObserverCannotObserveTwiceError if @target
  14      @target = target
  15      make_observable(target)
  16    end
  17    
  18    def self.instances
  19      @instances ||= {}
  20    end
  21    
  22    def self.new(*args)
  23      o = super
  24      instances[o.object_id] = o
  25      o
  26    end
  27    
  28    private
  29      def make_observable(target)
  30        methods_to_observe.each do |method|
  31          target.instance_eval %{
  32            def #{method}(*args, &block)
  33              observer = #{self.class}.instances[#{self.object_id}]
  34              observer.send(:before_#{method}, *args, &block) if observer.respond_to? :before_#{method}
  35              observer.result = super
  36              observer.send(:after_#{method}, *args, &block) if observer.respond_to? :after_#{method}
  37              observer.result
  38            end
  39          }
  40        end
  41      end
  42      
  43      def methods_to_observe
  44        (methods_for(:before) + methods_for(:after)).uniq
  45      end
  46      
  47      def methods_for(name)
  48        methods.grep(/^#{name}_/).map { |n| n.to_s.gsub(/^#{name}_/, '').intern }
  49      end
  50  en