说我具有以下结构:
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
。我需要完全解决此问题,因为以后我需要在该命名空间之外使用此常量。
答案 0 :(得分:2)
解析常数时,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