这听起来可能令人困惑,但我正在与一个由新人组成的小团队合作,并且我正在尝试抽象出 ruby 中的一些东西以使事情进行得更顺利。我遇到问题的部分是 namespace 。
基本上,使用 ruby 的命名空间可以创建为:
module EIF
module Core
module Entities
#stuff
end
end
end
或
module EIF
end
module EIF::Core
end
module EIF::Core::Entities
#some stuff
end
事实上,这真的很麻烦。我想要类似于 C# 的东西,您只需将命名空间定义为:
namespace EIF.Core.Entities
{
#Some stuff
}
并完成它。我通过使用 eval 创建模块(在将名称与正则表达式匹配之后)设法获得了类似的东西
def namespace(path)
if path.match(/^([A-Z][a-zA-Z0-9]*)(::[A-Z][a-zA-Z0-9_]*)*$/)
spaces = path.split("::")
code = ""
spaces.each { |m| code << "module #{m}\n" }
spaces.each { code << "end\n" }
eval(code)
else
raise ArgumentError, "'#{path}' is not a valid namespace"
end
end
结果是我现在可以执行以下操作:
namespace "EIF::Core::Entities"
class EIF::Core::Entities::Attirbute
#class code
end
现在是下一步。我想使用 ruby block 使内容更易于阅读,因此它看起来像:
namespace "EIF::Core::Entities" do
class Attribute
#class code
end
end
myAttribute = EIF::Core::Entities::Attribute.new
问题是,到目前为止,我发现在运行时创建模块的唯一方法是使用 eval,当我尝试将代码块滑入 eval 时,生成的类保留在根命名空间中。我试过 instance_eval、module_eval 和 class_eval,但出于某种原因,没有人在模块中创建类。
我有什么办法可以做到这一点?我现在不想放弃。
最佳答案
完成。
似乎当您使用 module_eval 添加一个类时,如:
My::Namespace.module_eval do
class MyClass
end
end
无论上下文如何,MyClass 的命名空间都解析为::。但是,通过写:
class self::MyClass
命名空间被解析为当前命名空间对象,因此生成的类定义将在 My::Namespace 中
我不知道为什么会这样,但至少我得到了一些工作。现在的问题是,虽然这更短,但 self 这个词是违反直觉的。
关于ruby - 如何在动态生成的模块中运行 Proc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6727508/