如何检查method_defined?来自类中使用的模块,并在包含该模块后定义了方法

问题描述

如何定义一个模块来检查使用该模块的类中是否存在实例方法。模块通常包含在文件的开头,而方法是在之后定义的。我正在使用 Rails。

带钩子的模块

module MyModule
  extend ActiveSupport::Concern

  included do
    raise "Foo" if method_defined? :bar
  end 
end 

以下代码中从未出现 Foo 错误,我怎样才能让它引发错误

class MyClass 
   include MyModule

   def bar
     puts "Hello from Bar"
   end 
end 

在以下代码中引发了 Foo 错误

class MyOtherClass 
   def bar
     puts "Hello from Bar"
   end 

   include MyModule
end 

解决方法

这是一个纯 Ruby 的答案。我不知道 Rails 是否支持 Ruby 不支持的回调,这在这里很有用。

正如@Amadan 所指出的,该模块不是读心者;要查看在类上定义的实例方法,需要在包含模块之前定义该方法。方法 Module#included 将包含它的模块作为参数。它需要它,因为执行该方法时 selfMyModule

module MyModule
  def self.included(mod)
    puts "self = #{self}"
    puts ":bar is defined" if mod.method_defined? :bar
    puts ":foo is defined" if mod.method_defined? :foo
    puts ":goo is defined" if mod.method_defined? :goo
  end
  def goo
  end  
end 
class MyClass 
  def bar
  end 
  include MyModule
end

印刷品

self = MyModule
:bar is defined
:goo is defined

注意Module#included是在MyModule(goo)中定义的实例方法包含在MyClass之后执行的。