From: John Higgins Date: 2011-07-12T02:28:35+09:00 Subject: [ruby-core:37999] [Ruby 1.9 - Bug #5015] method_added" is called in addition to "method_undefined Issue #5015 has been updated by John Higgins. Lazaridis Ilias wrote: > Magnus Holm wrote: > > But undef_method *does* actually add a new method: it adds a method > which prevents the superclass' method being called > [...] > > Whatever "undef_method" does, is an internal implementation detail, which should *not* call "method_added". What rule exactly says that internal implementations can't fire callbacks? You are specifically interested in internal implementation issues when you are interested in things like "method_added" - there is always a price to peeking under the hood. > > undef method > callback: added any_method # false callback, "any_method" was *not* added by user Where exactly is the rule that a method needs to be added by a user to having a callback fired? Using your vaunted "I want every literal String to fire initialize" concept - when a user "requires" a file at least 10-15 strings are created in the background for a variety of reasons - is your argument that the initialize method shouldn't fire for those because *the user* didn't create the strings? Where does one draw the line? The undef_method call performs a specific task which you have made an assumption as to why it would be done. Lets assume we look at a variation of the example in the docs class Parent def hello puts "In parent" end end class Child < Parent end c = Child.new c.hello class Child undef_method :hello # prevent any calls to 'hello' end c.hello Outputs: In Parent prog.rb:23: undefined method `hello' for # (NoMethodError) In this case I am most certainly adding a method to my Child class because I'm specifically stopping a call from going up to Parent when #hello is called. Whether I use a convenience method like undef_method or write something to throw the method myself - I need to insert something into the call chain to prevent #hello from firing on the Parent class. You've made the assumption, incorrectly, that this can only be used on methods that have been added to a class previous to a undef_method call - that's simply not the case at all. Folks again have taken a reasonable step to ensure that both speed and flexibility are met. You are at no disadvantage in terms of understanding what is occurring either because the callbacks fire in a deterministic order for you. You know that if you have a "undefined" callback fire that there is a "added" callback that has just fired - you can easily revert any tracking that the added callback did for you if you wanted to (except if you want to know which methods actual exist on a class because undef_method certainly can add a method to a class). ---------------------------------------- Bug #5015: method_added" is called in addition to "method_undefined http://redmine.ruby-lang.org/issues/5015 Author: Lazaridis Ilias Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: 1.9.2 When a method is undefined via "undef_method :any_method", the following methods are called back: * method_added * method_undefined The expected behaviour is that only "method_undefined" is called (similar to "remove_method"). - class String def self.method_added(id) puts "callback: added #{id.id2name}" end def self.method_undefined(id) puts "callback: undefined #{id.id2name}" end def self.method_removed(id) puts "callback: removed #{id.id2name}" end end puts "\nundef method (buildin)" class String undef_method :capitalize end puts "\ndefine method" class String def any_method(*args) nil end end puts "\nundef method" class String undef_method :any_method end puts "\ndefine method" class String def any_method(*args) nil end end puts "\nremove method" class String remove_method :any_method end - OUTPUT: undef method (buildin) callback: added capitalize callback: undefined capitalize define method callback: added any_method undef method callback: added any_method callback: undefined any_method define method callback: added any_method remove method callback: removed any_method -- http://redmine.ruby-lang.org