如何在Ruby中动态更改嵌套?
我使用模块作为名称空间,并希望用类动态填充它们,如:如何在Ruby中动态更改嵌套?,ruby,module,namespaces,metaprogramming,nested,Ruby,Module,Namespaces,Metaprogramming,Nested,我使用模块作为名称空间,并希望用类动态填充它们,如: module Module1 # ... end module Module2 # ... end [Module1, Module2].each do |the_module| the_module.module_eval do class ApiTest < ActiveSupport::TestCase # ... end end end 模块1 # ... 结束 模块2 # ..
module Module1
# ...
end
module Module2
# ...
end
[Module1, Module2].each do |the_module|
the_module.module_eval do
class ApiTest < ActiveSupport::TestCase
# ...
end
end
end
模块1
# ...
结束
模块2
# ...
结束
[Module1,Module2]。每个do都是| u模块|
_module.module_eval do
类ApiTest
module_eval
可以工作,除非它不改变嵌套,保留外部嵌套。因此,包含的常量不会嵌套在模块中
最初的动机是为各自模块中包含的不同API实现生成相同的测试。您需要使用:
如果新类需要一个超类,可以将其作为参数传递给。我相信我已经找到了一种方法
klass = Class.new(String)
klass.class_eval do
def custom?; return true; end
end
Module1.module_exec do
const_set :Custom, klass
end
Two::Custom.new.custom?
#=> true
Class::new
的第一个参数是超类
(继承自)我还没有测试过,但可能是这样的
[Module1, Module2].each do |the_module|
the_module.const_set("ApiTest", Class.new(ActiveSupport::TestCase) do
# ...
end)
end
这里还有另一个选项(注意“self:”)
模块1
# ...
结束
模块2
# ...
结束
[Module1,Module2]。每个do都是| u模块|
_module.module_eval do
类self::ApiTest
然后,您可以使用ModuleUtils.module\u path\u binding()
在任何嵌套模块上下文中执行代码,以获得一个绑定,该绑定可以作为第二个参数传递给eval()
更多信息请访问
[Module1, Module2].each do |the_module|
the_module.const_set("ApiTest", Class.new(ActiveSupport::TestCase) do
# ...
end)
end
module Module1
# ...
end
module Module2
# ...
end
[Module1, Module2].each do |the_module|
the_module.module_eval do
class self::ApiTest < ActiveSupport::TestCase
# ...
end
end
end
# Get ourselves a clean, top-level binding.
def main_binding
binding
end
module ModuleUtils
module ModuleMethods ; end
self.extend ModuleMethods
module ModuleMethods
# Get a binding with a Module.nesting list that contains the
# given module and all of its containing modules as described
# by its fully qualified name in inner-to-outer order.
def module_path_binding(mod)
raise ArgumentError.raise(
"Can't determine path nesting for a module with a blank name"
) if mod.name.to_s.empty?
m, b = nil, main_binding
mod.name.split('::').each do |part|
m, b =
eval(
"[ #{part} , #{part}.module_eval('binding') ]",
b
)
end
raise "Module found at name path not same as specified module" unless m == mod
b
end
end
end