Ruby method_added callback not starting, including modules

I wanted to write a small library called "Deprecate-It" and reused the method_added callback. But now I noticed that this callback does not start when the module is turned on.

Are there any callbacks or workarounds to get information about the Foobar class when some information is included?

A small demonstration 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

What is the result:

InstanceMethod: 'visible' added to 'Foobar'
invisible: true
visible: true
wont_exist: false

Additional Information:

I really need to use a hook, for example method_added.

ActiveModel adds public_instance_methods to the class at runtime, although anonymous modules.

+5
source share
3 answers

, - . , / , . , , .

, - method_added, . , .

, , include :

class Foobar
  def self.include(included_module)
    included_module.instance_methods.each{|m| self.method_added(m)}
    super
  end
end

, included Module - , .

+8

, , . , :

class Module
  def included(klass)
    if klass.respond_to?(:method_added)
      self.instance_methods.each do |method|
        klass.method_added(method)
      end
    end
  end
end

, , , method_added. , :

InstanceMethod: 'visible' added to 'Foobar'
InstanceMethod: 'invisible' added to 'Foobar'
invisible: true
visible: true
wont_exist: false

, , .

+3

I think that deprecationdoesn't really matter requiring a library. it is implemented as follows: datamapper. Oh method_addedhook; it works as expected because the methods are already added to modulenot class. Only you can get the expected result of beheading a monkey included.

# got from https://github.com/datamapper/dm-core/blob/master/lib/dm-core/support/deprecate.rb
module Deprecate
  def deprecate(old_method, new_method)
    class_eval <<-RUBY, __FILE__, __LINE__ + 1
      def #{old_method}(*args, &block)
        warn "\#{self.class}##{old_method} is deprecated, use \#{self.class}##{new_method} instead (\#{caller.first})"
        send(#{new_method.inspect}, *args, &block)
      end
    RUBY
  end
end # module Deprecate

class MyClass
  extend Deprecate

  def old_method
    p "I am old"
  end
  deprecate :old_method, :new_method

  def new_method
    p "I am new"
  end
end

m = MyClass.new
m.old_method

# MyClass#old_method is deprecated, use MyClass#new_method instead (pinger.rb:27:in `<main>')
# "I am new"
+1
source

All Articles