获取 Ruby 中任何给定模块的嵌套层次结构

Getting the nesting heirarchy for any given module in Ruby

我有一个方法需要能够访问模块定义的嵌套层次结构。假设我有这个定义:

module A
  module B
    module C
    end
  end
end

我正在尝试编写一个方法,如果将对 C 的引用传递给该方法,它能够 return Module.nesting 的结果,就好像它在定义中被调用。例如:

get_nesting(A::B::C) # => [A::B::C, A::B, A]

但是,我不知道如何在不同的上下文中调用 Module.nesting。我试过使用 instance_exec,但这只是 return 当前范围内的嵌套。

module X
  def self.get_nesting(m)
    m.instance_exec { Module.nesting }
  end
end

X.get_nesting(A::B::C) # => [X]

我想要 return [A::B::C, A::B, A] 代替。

有没有办法以这种方式使用 Module.nesting 或其他方式获得模块的嵌套?

试试这个:

module A
  module B
    module C
      Module.nesting
    end
  end
end
  #=> [A::B::C, A::B, A]

module A::B
  module C
    Module.nesting
  end
end
  #=> [A::B::C, A::B] 

A 未包含在最后一个 return 值中的原因是 nesting 取决于代码结构 ("lexical") 而不是 parent-child 模块的关系。出于这个原因,我认为任何导致 self 等于给定模块(方法的参数)然后执行 Module.nesting 的方法都注定要失败。

但是,您可以执行以下操作。

def get_nesting(mod)
  a = mod.to_s.split('::')
  a.size.times.map { |i| Module.const_get(a[0..i].join('::')) }.reverse
end

get_nesting(A)       #=> [A] 
get_nesting(A::B)    #=> [A::B, A] 
get_nesting(A::B::C) #=> [A::B::C, A::B, A] 

get_nesting(A::B::C).map { |m| m.class } 
  #=> [Module, Module, Module]

考虑到这取决于 Module#to_s,这将被归类为拼凑。