如何在动态生成的模块中运行 Proc?

发布于 2024-11-24 13:34:38 字数 1375 浏览 0 评论 0原文

这可能听起来令人困惑,但我正在与一个由新人组成的小团队合作,并且我正在尝试抽象出 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

回眸一笑 2024-12-01 13:34:38

完毕。

似乎当您使用 module_eval 添加类时,如下所示:

My::Namespace.module_eval do
  class MyClass
  end
end

无论上下文如何,MyClass 的命名空间都会解析为 :: 。但是,通过编写:

class self::MyClass

命名空间被解析为当前命名空间对象,因此生成的类定义将位于 My::Namespace 中,

我不知道为什么会发生这种情况,但至少我得到了一些工作。现在的问题是,虽然这个词更短,但“自我”这个词是违反直觉的。

Done.

It seems that when you add a class using module_eval, as in:

My::Namespace.module_eval do
  class MyClass
  end
end

The namespace for MyClass is resolved to :: regardless of the context. However, by writing:

class self::MyClass

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文