I wanted to write a little “Deprecate-It” lib and used the “method_added” callback a lot.
But now I noticed that this callback is not triggered, when including a module.
Are there any callbacks or workarounds, to get class “Foobar” informed when somewhing is included to itself?
Small Demo to demonstrate:
# Including Moduls won't trigger method_added callback
module InvisibleMethod
def invisible
"You won't get a callback from me"
end
end
class Foobar
def self.method_added(m)
puts "InstanceMethod: '#{m}' added to '#{self}'"
end
def visible
"You will get a callback from me"
end
include InvisibleMethod
end
[:invisible, :visible, :wont_exist].each do |meth|
puts "#{meth}: #{Foobar.public_method_defined? meth}"
end
That’s the result:
InstanceMethod: 'visible' added to 'Foobar'
invisible: true
visible: true
wont_exist: false
Additional Information:
I really need to use a hook like method_added.
ActiveModel is adding public_instance_methods to Class during runtime though anonymous Modules.
The problem is that including modules doesn’t add methods to the classes – it only changes the method call chain. This chain defines which classes/module will be searched for a method, that is not defined for the class in question. What happens when you include a module is an addition of an entry in that chain.
This is exactly the same as when you add a method in a superclass – this doesn’t call
method_addedsince it is not defined in the superclass. It would be very strange if a subclass could change the behavior of a superclass.You could fix that by manually calling method added for an included module, by redefining
includefor your class:And it is much safer than redefining the
includedmethod inModule– the change is narrowed only to the classes, that you have defined yourself.