Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reverse ruby's include function

Tags:

I'll explain what i'm looking for in code as thats probably the most succinct:

module Mixin   def method     puts "Foo"   end end  class Whatever   include Mixin end  w = Whatever.new w.method => "Foo"  # some magic here w2 = Whatever.new w.method => NoMethodError 

I had tried just undefining the Mixin module using remove_const, but this doesn't seem to make any difference to Whatever. I had assumed that #include just added a reference to the module into the class's method resolution chain - but this behaviour doesn't agree with that.

Can anyone tell me what include actually does behind the scenes, and how to reverse this?

like image 479
Glenjamin Avatar asked Mar 08 '10 17:03

Glenjamin


Video Answer


2 Answers

As it seems probably you want to accomplish these on instances instead of the whole class, so I would change klochner's code a bit to handle just one instance instead of all the instances of a class.

module ModuleRemover      def remove_module(mod, options = {})       metaclass = class << self; self end       mod.instance_methods.each {|method_name| metaclass.class_eval { undef_method(method_name.to_sym) }}     end  end 

As Mladen pointed out, it would be cool to avoid removing methods that are overwritten on the host class, so an [only, exclude] options for this method would be ideal.

>> c1 = C.new >> c1.foo => fooing >> c1.extend(ModuleRemover) >> c1.remove_module(Mod) >> c1.foo => NoMethodError: undefined method `foo' for #< C:0x11b0d90> >> c2 = C.new >> c2.foo => fooing 
like image 73
Roman Gonzalez Avatar answered Oct 12 '22 06:10

Roman Gonzalez


module Mod   def foo     puts "fooing"   end end  class C   include Mod   def self.remove_module(m)     m.instance_methods.each{|m| undef_method(m)}   end end  >> c = C.new >> c.foo fooing >> C.remove_module(Mod) => ["foo"] >> c.foo NoMethodError: undefined method `foo' for #&lt C:0x11b0d90>  
like image 45
klochner Avatar answered Oct 12 '22 08:10

klochner