gutopia-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [rgui-dev] Jumping Right In


From: Tom Sawyer
Subject: Re: [rgui-dev] Jumping Right In
Date: 08 Aug 2002 07:22:16 -0600

just finsihed debugging this puppy --the instance_variable autobinding.

considering whether to offer both types of bindings, instance_variables
and methods. oh, and i added class_variables too.

one neat side effect of this is an easy implemention of single level
undo for an object (could do mutiple-level if i stored a stack for each
instance rather then just the latest value)

anyway, here's the code:


class Object

  def bind(instance, proc=nil, &block)
    proc = block unless proc
    instance = instance.to_s
    ___automate___ unless @___procs___ and @___instances___
    @___procs___[instance] = proc
  end
  
  def ___automata___ #(*args, &block)
    (self.instance_variables | self.class.class_variables).each { |iv|
      if not ['@___instances___', '@___procs___'].include?(iv)
        current = instance_eval "#{iv}"
        if current != @___instances___[iv]
          @___instances___[iv] = current.dup
          if @___procs___.has_key?(iv)
            @___procs___[iv].call(current) #(*args, &block)
          end
        end
      end
    }
  end
  
  def ___automate___
    $___trigger___ = []  # not sure of best place to put this
    @___procs___ = {} unless @___procs___
    @___instances___ = {} unless @___instances___
    (self.instance_variables | self.class.class_variables).each { |iv|
      if not ['@___instances___', '@___procs___'].include?(iv)
        current = instance_eval "#{iv}"
        @___instances___[iv] = current.dup
      end
    }
    self.methods.each { |meth|
      if not Object.instance_methods(true).include?(meth)
        alias_meth = "___#{meth.hash.to_s.gsub('-', '_')}___"
        if not self.respond_to? alias_meth
          self.instance_eval <<-"EOS"
            class << self
              alias_method :#{alias_meth}, :#{meth}
              def #{meth}(*args, &block)
                return if $___trigger___.include?([self, :#{meth}])
                $___trigger___ << [self, :#{meth}]
                r = send(:#{alias_meth}, *args, &block)
                ___automata___ #(*args, &block)
                $___trigger___.pop
                return r
              end
            end
          EOS
        end
      end
    }
  end
  
end


and here is a dumb test case:


class TestObject

  attr_reader :one
  attr_writer :two
  attr_accessor :three, :four

  def initialize
    @one = 1
    @two = 2
    @three = [ 'john', 'joe' ]
    @four = { 'john' => 36, 'joe' => 34 }
  end

  def alt
    @four.update( { 'tom' => 32 } )
  end

end

testobj = TestObject.new

testobj.bind(:@one) { |x| puts "one is #{x}!" }
testobj.bind(:@two) { |x| puts "two is #{x}!" }
testobj.bind(:@three) { |x| puts "three is #{x}!" }
testobj.bind(:@four) { puts "four's one is #{testobj.one}!" }

testobj.two = 3
testobj.alt


gots to go now and prove david black is too synical. ;-) later...





reply via email to

[Prev in Thread] Current Thread [Next in Thread]