Removing a method in Ruby
There are several ways of adding a method to a ruby class (or instance), for example, define_method, method_missing, or by just opening up the class itself.
However, can we remove the methods from a Ruby class?
I encountered two ways of removing methods from a class:
There are subtle differences between the two. The former removes the method from the current class, where as the latter, stops responding to the methods in the current class.
Let’s look at an example for the same. Imagine we have a parent class, Appliance (a.k.a Kitchen Appliance), and child class, Can opener. Here are the definitions for the two classes:
class Appliance
def name
puts "I'm a kitchen appliance"
end
end
class CanOpener < Appliance
def name
puts "I'm a can opener"
end
end
Now, let’s try remove_method
and see what happens.
can_opener = CanOpener.new
can_opener.name
class CanOpener
remove_method :name
end
can_opener.name
puts "Can Opener has a name? #{can_opener.respond_to?(:name)}"
This will produce the following output:
I'm a can opener
I'm a kitchen appliance
Can Opener has a name? true
As soon as you remove a method from a class it treats the method as
undefined and goes up the ancestor chain to look for an implementation,
which it finds in the parent class. Since, there’s an implementation
respond_to
returns true.
However, undef_method
works slightly differently and let’s see how:
class Appliance
def name
puts "I'm a kitchen appliance"
end
end
class CanOpener < Appliance
def name
puts "I'm a can opener"
end
end
can_opener = CanOpener.new
can_opener.name
class CanOpener
undef_method :name
end
puts "Can Opener has a name? #{can_opener.respond_to?(:name)}"
can_opener.name
This will produce the following output:
I'm a can opener
Can Opener has a name? true
/tmp/execpad-f7201e261f52/source-f7201e261f52:21:in `<main>': undefined method `name' for #<CanOpener:0x41017dcc> (NoMethodError)
Unlike remove_method
, undef_method
stops responding to the method
and doesn’t travel up the ancestor chain. It totally disregards the
method implementation in the parent class.
Quite interesting, however, I’ve never seen it used in any of the production code before, so, hopefully, I will find a good use case for it soon.