如何在某些类的祖先中检测我的匿名模块

时间:2016-04-22 12:46:52

标签: ruby metaprogramming

在长期运行期间,我prepend外国人的班级与我的匿名模块(即时创建)。

在某些时候,给定一个任意类的实例,我需要列出我的匿名模块prepended。遗憾的是,与Module#new不同,Class#new不接受parent参数(换句话说,它们不能都具有相同的共同虚拟父级,我可以使用筛选< / em> my modules in all ancestors。)

我可以在每个匿名模块上定义一个特定的my_litmus_dummy_method,并在ancestors.select时检查它,但这很难看。

我可以include DummyLitmusModule在我的每个匿名模块中检查它是ancestors.select时的祖先,但这也很难看。

所以,我的问题是:是否有任何优雅的方式来标记我的匿名模块,以便稍后我可以轻松地将它们从所有模块列表中筛出来?

UPD 代码示例

def patch_class klazz
  klazz.send :prepend, Module.new { define_method(:my_method) {} }
end

...

# load list of classes from somewhere and patch them
classes = my_parse_yaml('config.yml')
classes.each do |c|
  patch_class c
end

...

# somewhere in other place
instance.patches # ⇐ I want to implement this

此时我需要^ W想知道,修补了哪些方法。我有点从Rails重新实现alias_method_chain,我想向我的界面用户报告“用法”。

2 个答案:

答案 0 :(得分:1)

修补Module#prepend怎么样?

class Module
  attr_reader :mods_prepended
  alias :old_prepend :prepend
  def prepend(*mods)
    @mods_prepended =|| {}
    (@mods_prepended[self] =|| []).concat(mods)
  end
  old_prepend(*mods)
end

class C
  def patches
    Module.mods_prepended[self.class]
  end
end

然后通过以下方式提供所需信息:

C.new.patches

答案 1 :(得分:0)

将您的匿名模块存储在某处,然后您就可以找到它们:

patches = [Module.new] # some other module
c = Class.new
m = Module.new
c.prepend m
patches << m

instance = c.new
used_patches = patches.select{|p| instance.is_a? p}