On Mon, Sep 1, 2008 at 3:39 PM, Jos=E9 Ignacio
<joseignacio.fernandez / gmail.com> wrote:
Maybe you want to use pushable behavior

class Behavior
 attr_reader :block
 def initialize &blk
   @block =3D blk
 end
end

module Kernel
 def Behavior &blk
   Behavior::new &blk
 end
end

class Module
 def empty?; instance_methods.empty? end
 def empty!; instance_methods.each do |im| remove_method im end end
end

module Pushable
 CannotPopException =3D Class::new RuntimeError
 ArgumentError      =3D Class::new ::ArgumentError

 def pop_behavior
   @__bsp__ -=3D 1
   raise CannotPopException, "empty entity #{self}" if @__bsp__ < 0
   @__behavior_stack__[@__bsp__].empty!
 end

 def push_behavior *behaviors, &blk
   @__behavior_stack__ ||=3D []
   @__bsp__ ||=3D 0
   raise ArgumentError,
     "push_behavior takes at least one behavior or block" if
       behaviors.empty? and blk.nil?

   behaviors.each do |behavior|
     _push_behavior  behavior
   end

   _push_behavior blk if blk
   self
 end

 private

 def _push_behavior behavior
   m =3D @__behavior_stack__[@__bsp__]
   @__behavior_stack__ << ( m =3D Module::new ) unless m
   include m rescue extend m # this is autoprotected against double
inclusion; so finally turns out it is a feature ;)
   m.empty!
   m.module_eval &(behavior.block rescue behavior)
   @__bsp__ +=3D 1
 end
end # module Pushable

class << Pushable
 def new *args, &blk
   c =3D Class::new( *args, &blk )
   c.extend self
   c
 end
end # class << Pushable

class << PushableModule =3D Module::new
 def new *args, &blk
   m =3D Module::new( *args, &blk )
   m.extend Pushable
   m
 end
end
------------------------------------ 8<

See these test cases to learn more about how to use this:

    o =3D Object.new
    o.extend Pushable
    b =3D Behavior do
      def a; 42 end
    end
    o.push_behavior b
    assert_equal 42, o.a
    o.pop_behavior
    assert_raise NoMethodError do o.a end

HTH
Robert

--=20
C'est v=E9ritablement utile puisque c'est joli.

Antoine de Saint Exup=E9ry