From: "evanwebb@..." Date: 2006-09-09T07:00:13+09:00 Subject: Re: better alias_method I encountered this same problem a while ago and also began to come up with a solution. One of my use cases was the now-common override of Kernel#require to provide some new behavior for requiring files. I came up with Maskable: http://hoshi.fallingsnow.net/svn/maskable/maskable.rb There is some sample code at the bottom of that file. You use it by putting your new implementations of methods in a Module and then calling Module#add_mask(ModuleWithNewImpl). I found it nice because it forces you to organizes your "mask" methods into the module to make them easier to understand. To call add_mask on the Module, you have to extend the module with Method::Maskable. But of course if you want to be able to mask any method in any class/module, you can just do Module.extend(Method::Maskable). For a mask to call the next method in the chain, It just calls Method.rest. Any thoughts? It's a little nasty, but works pretty well last I used it. ara.t.howard@noaa.gov wrote: > i've been wanting a better alias_method for quite some time. essentially i'd > like a way out of the trap where executing > > alias_method '__fubar__', 'fubar' > > goes haywire when __fubar__ already exists. we've all seen it happen before. > > anyhow. the interface it'd like would be > > > class C > def m() 'a' end > > push_method 'm' > > def m() super + 'b' end > end > > p C.new.m #=> 'ab' > > > what i've got is quite close, but no cigar. it has a fundemental problem with > the way ruby scopes super which i'm too tired atttm to figure out. i'm hoping > i can go to bed and wake up to a nice patch ;-) here's what i've got: > > > harp:~ > cat a.rb > class Module > def push_method m > this = self > > include Module.new{ > @m = this.instance_method m > > this.module_eval{ remove_method m } > > module_eval <<-code > def #{ m }(*a, &b) > um = ObjectSpace._id2ref #{ @m.object_id } > um.bind(self).call *a, &b > end > code > } > end > end > > class C > def m > 'a' > end > p new.m #=> 'a' > > > push_method 'm' > > > def m > super + 'b' > end > p new.m #=> 'ab' > > > push_method 'm' > > > def m > super + 'c' > end > p new.m #=> 'abc' > end > > > > harp :~ > ruby a.rb > "a" > "ab" > a.rb:31:in `m': stack level too deep (SystemStackError) > from (eval):3:in `m' > from a.rb:31:in `m' > from (eval):3:in `m' > from a.rb:31:in `m' > from (eval):3:in `m' > from a.rb:31:in `m' > from (eval):3:in `m' > from a.rb:31:in `m' > ... 2343 levels... > from a.rb:31:in `m' > from (eval):3:in `m' > from a.rb:40:in `m' > from a.rb:42 > > > have at it - i'll be back in 8 hrs. ;-) > > > -a > -- > what science finds to be nonexistent, we must accept as nonexistent; but what > science merely does not find is a completely different matter... it is quite > clear that there are many, many mysterious things. > - h.h. the 14th dalai lama