Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending ruby object; extend_object callback prevents instance methods from being extended

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

2 Answers

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
like image 134
tomafro Avatar answered Jan 31 '26 19:01

tomafro


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


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!