From: ara.t.howard@... Date: 2006-12-29T02:01:35+09:00 Subject: Re: override.rb ---1400102478-551175305-1167325293=:5000 Content-Type: MULTIPART/MIXED; BOUNDARY="-1400102478-551175305-1167325293=:5000" This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. ---1400102478-551175305-1167325293=:5000 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed On Thu, 28 Dec 2006, Devin Mullins wrote: > ara.t.howard@noaa.gov wrote: >> since the threads split all over the place i figured i'd start yet another. >> can people break this? > well... yes! i ran it, and got: > "a" > a.rb:63:in `override': private method `remove_method' called for C:Class > (NoMethodError) > from a.rb:61:in `each' > from a.rb:61:in `override' > from a.rb:102 how odd. which ruby version? > then, once I fixed that: > > $ cat b.rb > require 'a' > > class C > c = new > > def M; 'a' end > def m; 'A' end > p c.M(), c.m > > override { def M; super + 'b' end; def m; super + 'B' end } > p c.M(), c.m > > restore 'M' > p c.M(), c.m > > restore 'm' > p c.M(), c.m > end > > $ ruby b.rb > "a" > "A" > ./a.rb:32: warning: already initialized constant M hmmm. i reworked to use a single constant table of methods. latest below and attached. -a -- if you find yourself slandering anybody, first imagine that your mouth is filled with excrement. it will break you of the habit quickly enough. - the dalai lama class Module module OverRiding class << self def new Module.new{ @added_methods = [] @parent = nil class << self attr :added_methods attr :parent def method_added m super if defined? super ensure added_methods << m.to_s end def delete_method m remove_method m added_methods.delete_at(added_methods.rindex(m.to_s)) end def add_parent m include(@parent = m) end def cache mname, m mname = mname.to_s const_set :METHODS____, {} unless const_defined? :METHODS____ const_get(:METHODS____)[ mname ] = m module_eval <<-code def #{ mname } *a, &b METHODS____[ '#{ mname }' ].bind(self).call *a, &b end code end def walking_up m = self loop{ yield m break unless((m=m.parent) rescue nil) } end end } end end end def overriding &b this = self m = OverRiding.new m.module_eval &b unless defined? @overriding @overriding = OverRiding.new m.added_methods.each do |mname| @overriding.cache mname, this.instance_method(mname) remove_method mname end end m.add_parent @overriding include m @overriding = m end alias_method 'override', 'overriding' def restoring *_a, &_b if _b # barewords will restore methods o = Object.new sc = class << o; self; end sc.module_eval{ instance_methods.each{|m| remove_method m unless m[/^__/] rescue nil} define_method('method_missing'){|__m, *__a| _a << __m; self } } o.instance_eval &_b end _a.flatten.compact.map do |mname| if defined? @overriding mname = mname.to_s @overriding.walking_up do |m| break( m.delete_method mname ) if m.added_methods.include?(mname) end end instance_method mname end end alias_method 'restore', 'restoring' end if $0 == __FILE__ class C c = new def m() 'a' end p c.m #=> 'a' override{ def m() super + 'b' end } p c.m #=> 'ab' override{ def m() super + 'c' end } p c.m #=> 'abc' override{ def m() super + 'd' end } p c.m #=> 'abcd' restore 'm' p c.m #=> 'abc' restore 'm' p c.m #=> 'ab' restore 'm' p c.m #=> 'a' end end ---1400102478-551175305-1167325293=:5000 Content-Type: TEXT/PLAIN; charset=US-ASCII; name=override.rb Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Content-Disposition: attachment; filename=override.rb Y2xhc3MgTW9kdWxlDQogIG1vZHVsZSBPdmVyUmlkaW5nDQogICAgY2xhc3Mg PDwgc2VsZg0KICAgICAgZGVmIG5ldw0KICAgICAgICBNb2R1bGUubmV3eyAN CiAgICAgICAgICBAYWRkZWRfbWV0aG9kcyA9IFtdIA0KICAgICAgICAgIEBw YXJlbnQgPSBuaWwNCg0KICAgICAgICAgIGNsYXNzIDw8IHNlbGYNCiAgICAg ICAgICAgIGF0dHIgOmFkZGVkX21ldGhvZHMNCiAgICAgICAgICAgIGF0dHIg OnBhcmVudA0KDQogICAgICAgICAgICBkZWYgbWV0aG9kX2FkZGVkIG0NCiAg ICAgICAgICAgICAgc3VwZXIgaWYgZGVmaW5lZD8gc3VwZXINCiAgICAgICAg ICAgIGVuc3VyZQ0KICAgICAgICAgICAgICBhZGRlZF9tZXRob2RzIDw8IG0u dG9fcw0KICAgICAgICAgICAgZW5kDQoNCiAgICAgICAgICAgIGRlZiBkZWxl dGVfbWV0aG9kIG0NCiAgICAgICAgICAgICAgcmVtb3ZlX21ldGhvZCBtDQog ICAgICAgICAgICAgIGFkZGVkX21ldGhvZHMuZGVsZXRlX2F0KGFkZGVkX21l dGhvZHMucmluZGV4KG0udG9fcykpDQogICAgICAgICAgICBlbmQNCg0KICAg ICAgICAgICAgZGVmIGFkZF9wYXJlbnQgbQ0KICAgICAgICAgICAgICBpbmNs dWRlKEBwYXJlbnQgPSBtKQ0KICAgICAgICAgICAgZW5kDQoNCiAgICAgICAg ICAgIGRlZiBjYWNoZSBtbmFtZSwgbQ0KICAgICAgICAgICAgICBtbmFtZSA9 IG1uYW1lLnRvX3MNCiAgICAgICAgICAgICAgY29uc3Rfc2V0IDpNRVRIT0RT X19fXywge30gdW5sZXNzIGNvbnN0X2RlZmluZWQ/IDpNRVRIT0RTX19fXw0K ICAgICAgICAgICAgICBjb25zdF9nZXQoOk1FVEhPRFNfX19fKVsgbW5hbWUg XSA9IG0NCiAgICAgICAgICAgICAgbW9kdWxlX2V2YWwgPDwtY29kZQ0KICAg ICAgICAgICAgICAgIGRlZiAjeyBtbmFtZSB9ICphLCAmYg0KICAgICAgICAg ICAgICAgICAgTUVUSE9EU19fX19bICcjeyBtbmFtZSB9JyBdLmJpbmQoc2Vs ZikuY2FsbCAqYSwgJmINCiAgICAgICAgICAgICAgICBlbmQNCiAgICAgICAg ICAgICAgY29kZQ0KICAgICAgICAgICAgZW5kDQoNCiAgICAgICAgICAgIGRl ZiB3YWxraW5nX3VwDQogICAgICAgICAgICAgIG0gPSBzZWxmDQogICAgICAg ICAgICAgIGxvb3B7DQogICAgICAgICAgICAgICAgeWllbGQgbQ0KICAgICAg ICAgICAgICAgIGJyZWFrIHVubGVzcygobT1tLnBhcmVudCkgcmVzY3VlIG5p bCkNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZW5kDQogICAgICAg ICAgZW5kDQogICAgICAgIH0NCiAgICAgIGVuZA0KICAgIGVuZA0KICBlbmQN Cg0KICBkZWYgb3ZlcnJpZGluZyAmYg0KICAgIHRoaXMgPSBzZWxmDQogICAg bSA9IE92ZXJSaWRpbmcubmV3DQogICAgbS5tb2R1bGVfZXZhbCAmYg0KDQog ICAgdW5sZXNzIGRlZmluZWQ/IEBvdmVycmlkaW5nIA0KICAgICAgQG92ZXJy aWRpbmcgPSBPdmVyUmlkaW5nLm5ldw0KICAgICAgbS5hZGRlZF9tZXRob2Rz LmVhY2ggZG8gfG1uYW1lfA0KICAgICAgICBAb3ZlcnJpZGluZy5jYWNoZSBt bmFtZSwgdGhpcy5pbnN0YW5jZV9tZXRob2QobW5hbWUpDQogICAgICAgIHJl bW92ZV9tZXRob2QgbW5hbWUNCiAgICAgIGVuZA0KICAgIGVuZA0KDQogICAg bS5hZGRfcGFyZW50IEBvdmVycmlkaW5nDQogICAgaW5jbHVkZSBtIA0KICAg IEBvdmVycmlkaW5nID0gbQ0KICBlbmQNCiAgYWxpYXNfbWV0aG9kICdvdmVy cmlkZScsICdvdmVycmlkaW5nJw0KDQogIGRlZiByZXN0b3JpbmcgKl9hLCAm X2INCiAgICBpZiBfYiAjIGJhcmV3b3JkcyB3aWxsIHJlc3RvcmUgbWV0aG9k cw0KICAgICAgbyA9IE9iamVjdC5uZXcNCiAgICAgIHNjID0gY2xhc3MgPDwg bzsgc2VsZjsgZW5kDQogICAgICBzYy5tb2R1bGVfZXZhbHsNCiAgICAgICAg aW5zdGFuY2VfbWV0aG9kcy5lYWNoe3xtfCByZW1vdmVfbWV0aG9kIG0gdW5s ZXNzIG1bL15fXy9dIHJlc2N1ZSBuaWx9DQogICAgICAgIGRlZmluZV9tZXRo b2QoJ21ldGhvZF9taXNzaW5nJyl7fF9fbSwgKl9fYXwgX2EgPDwgX19tOyBz ZWxmIH0NCiAgICAgIH0NCiAgICAgIG8uaW5zdGFuY2VfZXZhbCAmX2INCiAg ICBlbmQNCiAgICBfYS5mbGF0dGVuLmNvbXBhY3QubWFwIGRvIHxtbmFtZXwN CiAgICAgIGlmIGRlZmluZWQ/IEBvdmVycmlkaW5nDQogICAgICAgIG1uYW1l ID0gbW5hbWUudG9fcw0KICAgICAgICBAb3ZlcnJpZGluZy53YWxraW5nX3Vw IGRvIHxtfA0KICAgICAgICAgIGJyZWFrKCBtLmRlbGV0ZV9tZXRob2QgbW5h bWUgKSBpZiBtLmFkZGVkX21ldGhvZHMuaW5jbHVkZT8obW5hbWUpDQogICAg ICAgIGVuZA0KICAgICAgZW5kDQogICAgICBpbnN0YW5jZV9tZXRob2QgbW5h bWUNCiAgICBlbmQNCiAgZW5kDQogIGFsaWFzX21ldGhvZCAncmVzdG9yZScs ICdyZXN0b3JpbmcnDQplbmQNCg0KDQoNCg0KaWYgJDAgPT0gX19GSUxFX18N Cg0KICBjbGFzcyBDDQogICAgYyA9IG5ldw0KDQogICAgZGVmIG0oKSAnYScg ZW5kDQogICAgcCBjLm0gIz0+ICdhJw0KDQogICAgb3ZlcnJpZGV7IGRlZiBt KCkgc3VwZXIgKyAnYicgZW5kIH0NCiAgICBwIGMubSAjPT4gJ2FiJw0KDQog ICAgb3ZlcnJpZGV7IGRlZiBtKCkgc3VwZXIgKyAnYycgZW5kIH0NCiAgICBw IGMubSAjPT4gJ2FiYycNCg0KICAgIG92ZXJyaWRleyBkZWYgbSgpIHN1cGVy ICsgJ2QnIGVuZCB9DQogICAgcCBjLm0gIz0+ICdhYmNkJw0KDQogICAgcmVz dG9yZSAnbScNCiAgICBwIGMubSAjPT4gJ2FiYycNCg0KICAgIHJlc3RvcmUg J20nDQogICAgcCBjLm0gIz0+ICdhYicNCg0KICAgIHJlc3RvcmUgJ20nDQog ICAgcCBjLm0gIz0+ICdhJw0KICBlbmQNCg0KZW5kDQo= ---1400102478-551175305-1167325293=:5000-- ---1400102478-551175305-1167325293=:5000--