views:

324

answers:

2

Having some trouble extending an object instance with a module, specifically when I define an extend_object callback in the Module class. My understanding is that when you do something like:

(s = String.new).extend SomeModule

The SomeModule extend_object callback is called. This seems to be the case, but when I include a callback, none of the instance methods defined in SomeModule are visible in the object. Some code should better explain this:

module M1
  def self.extend_object(o)
  end

  def test_method
    true
  end
end

module M2
  def test_method
    true
  end
end

(x = String.new).extend(M1)
(y = String.new).extend(M2)

Then,

x.methods.include?("test_method")
=> false
y.methods.include?("test_method")
=> true

More specifically,

x.singleton_methods
=> []
y.singleton_methods
=> ["test_method"]

Any ideas?

Reference:

http://www.ruby-doc.org/core/classes/Module.html#M001660
http://www.ruby-doc.org/core/classes/Object.html#M000337
+1  A: 

Got some help from a colleague, and realized I need to call super else it's a noop. Thanks.

+2  A: 

You should use the extended callback rather than overriding extend_object. The first is called when an object is extended by your module. The latter is called to actually extend the object. It's like the difference between included and append_features.

Here's an example:

module M1
  def self.extended(base)
    puts "extended object #{base.inspect}"
  end

  def test_method
    true
  end
end

Then:

>> (x = String.new).extend(M1)
extended object ""
=> ""

>> x.methods.include?("test_method")
=> true
tomafro