Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to reverse the included module in a class?

You include the modules in classes to extend the class functionality in terms of both adding class methods and instance methods to that particular class.

module M
 def self.class_method_from_module
  'from class_method_from_module'
 end

 def instance_method_from_module
  'from instance_method_from_module'
 end
end

class C
 include M

 def self.class_method
  'from class_method'
 end

 def instance_method
  'from instance_method'
 end
end

puts C.class_method => 'from class_method'

puts C.class_method_from_module => 'from class_method_from_module'

puts C.new.instance_method => 'from instance_method'

puts C.new.instance_method_from_module => 'instance_method_from_module'

Now even after removing the module M from the memory with the following:

Object.send(:remove_const, :M) #remove the module M

puts C.class_method_from_module => 'from class_method_from_module'

puts C.new.instance_method_from_module => 'instance_method_from_module'

instead of method missing. Why is that? What is the best way to remove the functionality added by a module to a class?

like image 630
Dharam Gollapudi Avatar asked Jun 19 '09 18:06

Dharam Gollapudi


People also ask

Can a module include another module Ruby?

In Ruby we don't have multiple inheritance, but we can include as many modules as we want, so they give us the same feature, without all the hassle that multiple inheritance usually brings to a language.

When to use include VS extend Ruby?

In simple words, the difference between include and extend is that 'include' is for adding methods only to an instance of a class and 'extend' is for adding methods to the class but not to its instance.

What is the difference between a class and a module?

What is the difference between a class and a module? Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).

Can a class be a module?

A class can be implemented in one or more . py files (modules). But often, we can organize a set of variables and functions into a class definition or just simply put them in a . py file and call it a module.


2 Answers

The details vary by implementation, but I know that at least in JRuby and MRI 1.8 there is a construct called an Include Class that is inserted in to the inheritance chain of a class when a Module is extended or included. The Module therefore won't be garbage collected, since the Include Class still refers to it, and the methods will still be on your class. There are some great articles by Patrick Farley on this and related topics in his blog.

So, to "remove" a module, you could individually undefine each method that came from the module, but that's a pretty unwieldy mechanism for that purpose. If using a gem is acceptable to you, it would probably be better would be to use Mixology, which was designed specifically for the purpose of adding and removing modules dynamically.

like image 176
John Hyland Avatar answered Oct 01 '22 20:10

John Hyland


When you include a mixin in a class, you are effectively adding the methods defined in the module to the class, or replacing methods in the class with those in the module that have the same name. The class does not have any tie to the module, which is why 'undefining' the M module won't affect class C. All that does is prevent you from mixing in M beyond that point.

You could use undef_method to remove methods from class C, but that will have side effects, potentially -- if a method was overriden by including a module, you will not get the original back, for instance. Undefining a class method is kind of ugly.

C.send(:undef_method, :instance_method_from_module)
class << C
  self
end.send(:undef_method, :class_method_from_module)
like image 41
Daniel Vandersluis Avatar answered Oct 01 '22 19:10

Daniel Vandersluis