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 #<Child:0x401b3bb4> (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