元ネタ:
require 'objspace' class C using Module.new { refine(C) { def hi puts "hi" end } } end def reachable?(from:, to:) ObjectSpace.reachable_objects_from(from).include?(to) end def rob(klass) modules = ObjectSpace.each_object(Module).to_a reachable_modules_to_klass = modules.select do |mod| next false unless mod.instance_of?(Module) reachable?(from: mod, to: klass) end res = [] modules.each do |mod| next unless mod.instance_of?(Module) reachable_modules_to_klass.each do |r| ObjectSpace.reachable_objects_from(mod).each do |x| next unless x.is_a?(ObjectSpace::InternalObjectWrapper) next unless x.type == :T_HASH next unless reachable?(from: x, to: r) res << mod end end end res end p rob(C) # => [#<Module:0x00005651666789b0>] class D < C using(*rob(C)) def hi2 hi end end D.new.hi2 # => hi
ちゃんと検証してないから要らないModuleも引っ張ってきてしまいそうだけど、とりあえずrefineしているモジュールを取り出すことには成功している。