说我有以下结构:
module Library
class DSL
def met(str)
# load `str` here; for this case, `MyApplication::MyClass`
end
end
class Superclass
extend DSL
end
end
module MyApplication
class MySubclass < Library::Superclass
met 'MyClass'
end
class MyClass
end
end
在Library::DSL#met
里面我需要加载常量str
,它以字符串形式提供。显然,如果我只是做Object.const_get(str)
它不起作用。
我需要以某种方式在当前范围的背景下完全解决str
(MyApplication::MySubclass
);因此,str
将被解决为MyApplication::MyClass
。我需要完全解决这个问题,因为稍后我需要在此命名空间之外使用此常量。
在解析常量时,Ruby首先检查模块的当前嵌套,然后检查最内层模块的祖先。
这可以通过遍历Module.nesting
和Module.nesting.first.ancestors
(按此顺序)来复制。如果模块定义了常量,我们可以通过const_get
获取它的值:
class A
class B
def met
str = 'C'
mods = Module.nesting
mods.concat(mods.first.ancestors)
mod = mods.find { |c| c.const_defined?(str, false) }
mod.const_get(str)
end
end
class C
end
end
A::B.new.met #=> A::C