From: Robert Dober Date: 2006-08-29T17:36:39+09:00 Subject: Re: Partial append_features? ------=_Part_4997_29989703.1156840595043 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On 8/29/06, Mauricio Fernandez wrote: > > On Tue, Aug 29, 2006 at 03:26:58PM +0900, Ola Bini wrote: > > Logan Capaldo wrote: > > >% cat Projects/Ruby Experiments/append_from.rb > > >class Module > > > def append_from( mod, *methods_to_keep ) > > > methods_to_keep.map! { |m| m.to_s } > > > methods_to_remove =3D mod.instance_methods(false) - methods_to_kee= p > > > new_mod =3D Module.new > > > new_mod.module_eval do > > > include mod > > > methods_to_remove.each { |meth| undef_method meth } > > > end > > > include new_mod > > > end > > >end > > > > > > > Thank you for writing it up for me. This was more or less what I had in > > mind of writing up myself. This solution is definitely the best for me, > > since the methods I want to keep is a small subset compared to how many > > to remove, and the ones to remove will grow with time. > > The above code effectively removes inherited methods too (as well as thos= e > from other modules that were included previously): > > class Module > def append_from( mod, *methods_to_keep ) > methods_to_keep.map! { |m| m.to_s } > methods_to_remove =3D mod.instance_methods(false) - methods_to_keep > new_mod =3D Module.new > new_mod.module_eval do > include mod > methods_to_remove.each { |meth| undef_method meth } > end > include new_mod > end > end > > module A; def foo; "A#foo" end end > module B > def foo; "B#foo" end > def bar; "B#bar" end > end > class X; include A end > x =3D X.new > x.foo # =3D> "A#foo" > class X; append_from B, :bar end > x.bar # =3D> "B#bar" > x.foo # =3D> > > # ~> -:24: undefined method `foo' for # (NoMethodError) > > In this example, #undef_method has blocked A#foo too. > > > Here's another way to do it without clobbering inherited methods; the > key difference is that the original module will not be added to the > inheritance chain: Brilliant, the is_a? relation should not hold anyway after a partial include, that was kind of where I blocked. RUBY_VERSION # =3D> "1.8.5" > RUBY_RELEASE_DATE # =3D> "2006-08-25" > class Module > def append_from(mod, *methods) > methods.map!{|x| x.to_s} > m =3D mod.clone > m.module_eval do > (instance_methods(false) - methods).each{|x| remove_method x } > end > include m > end > end > > module A; def foo; "A#foo" end end > module B > def foo; "B#foo" end > def bar; "B#bar" end > end > class X; include A end > x =3D X.new > x.foo # =3D> "A#foo" > class X; append_from B, :bar end > x.bar # =3D> "B#bar" > x.foo # =3D> "A#foo" > X.ancestors # =3D> [X, #, A, Object, > Kernel] > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D > B(') is missing in > the inheritance chain > > -- > Mauricio Fernandez - http://eigenclass.org - singular Ruby > > That is great work, thank you, well thank you for showing us, I think the feature itself is not desireable, but it is desireable to know how to do it ;) Cheers Robert --=20 Deux choses sont infinies : l'univers et la b=EAtise humaine ; en ce qui concerne l'univers, je n'en ai pas acquis la certitude absolue. - Albert Einstein ------=_Part_4997_29989703.1156840595043--