Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use undef_method, and when to use remove_method?

I want to redefine a method, but avoid the warning associated with it. Should I use undef_method or remove_method to do so?

(Yes, redefining methods is a little hacky. I'm doing this because I have some memoization that I want to use when unit tests are being run, but not when the program itself is run.)

like image 719
Andrew Grimm Avatar asked Aug 10 '12 01:08

Andrew Grimm


1 Answers

From the fine manual:

undef_method(symbol) → self

Prevents the current class from responding to calls to the named method. Contrast this with remove_method, which deletes the method from the particular class; Ruby will still search superclasses and mixed-in modules for a possible receiver.

So a remove_method like this:

class CC < C
  remove_method :m
end

is essentially the opposite of this:

class CC < C
  def m
  end
end

Where def m adds the method m to the class, remove_method :m removes m. But, if the super class has an m method, then that will still be used.

undef_method, OTOH, is more like this:

class CC < C
  def m
    raise 'No, you cannot do that.'
  end
end

So undef_method doesn't actually remove the method, it replaces the method with a special internal flag that causes Ruby to complain if you try to call that method.

Sounds like you're trying to replace an existing method and replace is semantically the same as a remove followed by an add so remove_method is probably more appropriate. However, if you want to be paranoid and make sure the replacement method is in place, then undef_method would be useful; or, if for some reason you need to remove the method in one place and add it in another, undef_method would at least tell you that you only did half the job whereas remove_method would either leave you with the super class's implementation (and possible strange bugs) or a rather confusing NoMethodError.

like image 106
mu is too short Avatar answered Oct 22 '22 17:10

mu is too short