如何在动态生成的模块中运行 Proc?
这可能听起来令人困惑,但我正在与一个由新人组成的小团队合作,并且我正在尝试抽象出 ruby 中的一些东西,以使事情进行得更顺利。我遇到问题的部分是命名空间。
基本上,使用 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,但由于某种原因,没有一个在模块中创建类。
我有什么办法可以做到这一点吗?我现在不愿意放弃。
It might sound confusing, but I'm working with a small team of newcomers, and I'm trying to abstract away some things in ruby to make things go more smoothly. The part I'm having problems with is namespaces.
Basically, namespaces with ruby can be created as:
module EIF
module Core
module Entities
#stuff
end
end
end
or
module EIF
end
module EIF::Core
end
module EIF::Core::Entities
#some stuff
end
Thing is, this is honestly cumbersome. I wanted something akin to C# where you simply define the namespace as:
namespace EIF.Core.Entities
{
#Some stuff
}
And be done with it. I managed to get something similar by using eval to create the modules (after matching the name to a regular expression)
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
The result is that I can now do the following:
namespace "EIF::Core::Entities"
class EIF::Core::Entities::Attirbute
#class code
end
Now comes the next step. I want to use a ruby block to make things easier to read, so that it will look like:
namespace "EIF::Core::Entities" do
class Attribute
#class code
end
end
myAttribute = EIF::Core::Entities::Attribute.new
The problem is that so far, the only method I have found to create the modules on runtime is with eval, and when I try to slip the code block into eval, the resulting class remains in the root namespace. I've tried instance_eval, module_eval, and class_eval, and none create the class within the modules for some reason.
Any way I can do this? I'd hate to give up now.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
完毕。
似乎当您使用 module_eval 添加类时,如下所示:
无论上下文如何,MyClass 的命名空间都会解析为 :: 。但是,通过编写:
命名空间被解析为当前命名空间对象,因此生成的类定义将位于 My::Namespace 中,
我不知道为什么会发生这种情况,但至少我得到了一些工作。现在的问题是,虽然这个词更短,但“自我”这个词是违反直觉的。
Done.
It seems that when you add a class using module_eval, as in:
The namespace for MyClass is resolved to :: regardless of the context. However, by writing:
The namespace is resolved to the current namespace object, thus the resulting class definition will be in My::Namespace
I don't know why this happens, but at least I got something working. Now the problem is that while this is shorter, the word self is counter-intuitive.