On Thu, 27 Apr 2006, Geoff Stanley wrote: > Hello all. > > I'm working on a plugin system for a IRC client I'm currently making. > The current plan is for plugins to extend the base classes of the > program. Often a plugin will need to add a little bit of functionality > to an already existing method in an already existing class. > > For example, I've got a logging plugin. I want it to extend the Channel > class to allow for logging of conversations. It needs to redefine > Channel's initialize method to open a log file. But it can't eliminate > all the important things the base initialize method did. > > I've thought about doing this with alias, but I haven't succeeded. My > thoughts were to rename 'initialize' to 'old_initialize', then have the > plugin redefine 'initialize'. In code: > > class Channel > alias old_initialize initialize > def initialize > old_initialize > # Then write custom code. (To open a log file, for example.) > end > end > > This doesn't work, however, because it leads to a stack overflow. I > think the reason for the overflow is because, when this is done twice, > old_initialize will call itself recursively with no end. > > Anyone have any ideas for how this could be done? It doesn't have to use > alias, but the general intention is thus: I want to redefine a method > and 'copy and paste' the old code from the method into the new method at > a given point. Sort of like using 'super', but no inheritence required. > > Thanks! Responses are greatly appreciated. harp:~ > cat a.rb class Module def def__ m, &b __m__, m = %W( __#{ m }__ #{ m } ) unless(instance_method(__m__) rescue nil) alias_method __m__, m module_eval <<-code def #{ m }(*__a__, &__b__) ret = nil #{ __m__ }(*__a__, &__b__) __mblocks__ = self.class.__mblocks__['#{ m }'] __mblocks__.each{|b| ret = instance_eval(&b)} ret end code end __mblocks__[m] << b self end def __mblocks__ @__mblocks__ ||= Hash::new{|h,k| h[k] = []} end end class C def foo p 0 end def__ 'foo' do p 1 end end c = C.new c.foo puts C.def__(:foo){ p 2 } c.foo puts C.def__(:foo){ p 3 }.def__(:foo){ p self => 42 } c.foo puts harp:~ > ruby a.rb 0 1 0 1 2 0 1 2 3 {#<C:0xb75d05f8>=>42} regards. -a -- be kind whenever possible... it is always possible. - h.h. the 14th dali lama