这可能听起来令人困惑,但我正在与一个小团队的新人合作,而我正试图用红宝石中的一些东西来抽象,以使事情变得更顺利。我遇到问题的部分是命名空间。
基本上,具有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块来使事情更容易阅读,因此它看起来像:
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,并且由于某种原因没有在模块中创建类。
我能做到这一点吗?我现在不想放弃。
答案 0 :(得分:2)
完成。
使用module_eval添加类时,似乎如下:
My::Namespace.module_eval do
class MyClass
end
end
MyClass的名称空间被解析为::而不管上下文如何。但是,写下:
class self::MyClass
命名空间被解析为当前的命名空间对象,因此生成的类定义将位于My :: Namespace
中我不知道为什么会这样,但至少我得到了一些工作。现在的问题是,虽然这个更短,但是自我这个词是违反直觉的。