2007/7/31, ara.t.howard <ara.t.howard / gmail.com>:
> i played some cannot seem to come up with a way to avoid having the
> stack of modules and also maintain super semantics across multiple
> invocations - anyone else have a go?

Ara, I didn't mean you don't need a stack of modules, but you don't
need to store the modules in an array (yet).

> just playing now.  patches welcome! ;-)

Not a patch, but a slightly different implementation based on your idea:

class C
    def foo() 'f' end
    def bar() 'b' end
    def foobar() foo + bar end
  end
  c = C.new
  p c.foobar        # => "fb"

  class C
    redefining do
      def foo() super + 'oo' end
    end
  end
  p c.foobar        # => "foob"

  class C
    redefining do
      def bar() super + 'ar' end
    end
  end
  p c.foobar        # => "foobar"

  class C
    redefining do
      def foo() super.reverse end
      def bar() super.reverse end
    end
  end
  p c.foobar        # => "oofrab"


  ### the implementation

  BEGIN {
    class Class
      def redefining &block
        unless defined? @_org
          org_mod = Module.new
          @_org = { :mod => org_mod }
          include org_mod
        end

        m = Module.new(&block)

        (m.instance_methods(false) & instance_methods(false)).each do |method|
          @_org[method] = instance_method method
          @_org[:mod].module_eval <<-EOC
            def #{method}(*a, &b)
              org = self.class.instance_variable_get("@_org")
              org["#{method}"].bind(self).call(*a, &b)
            end
          EOC
          remove_method method
        end

        include m
      end
    end
  }

I used the old way of getting at the original method (storing it
somewhere), because I'm not sure whether the garbage collector could
remove it if you only remember it's object_id.

Regards,
Pit