【问题标题】:How to check method_defined? from a module thats used in class with a method defined after the module is included如何检查定义的方法?来自在类中使用的模块,其中包含模块后定义的方法
【发布时间】:2021-08-26 00:17:17
【问题描述】:

如何定义一个模块来检查使用该模块的类中是否存在实例方法。该模块通常包含在文件的开头,而方法是在之后定义的。我正在使用 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 在类定义中执行指令,就像任何其他指令序列一样,一条一条地执行。当时include MyModuleMyClass还没有bar。您需要一台时间机器才能知道bar 将在未来被定义。
  • 写一个异常块。如果未定义该方法,它将引发错误,因此您可以使用一些代码块来挽救它

标签: ruby-on-rails ruby module mixins


【解决方案1】:

这是一个纯 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之后执行的。

【讨论】:

  • MyModule 不必是读心者,也可以是观察者。可以使用Module#method_added 来观察bar 的定义并在该事件中引发。
猜你喜欢
  • 2012-07-26
  • 2017-12-19
  • 2013-04-30
  • 2023-03-17
  • 2020-04-04
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 2013-05-17
相关资源
最近更新 更多