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

标签 ruby module eval block dsl

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

相关文章:

matlab - 如何在 Matlab R2013a 中使用 eval 将符号 var s 替换为 tf ('s')

php - 是否可以在 PHPStorm 中突出显示 Ruby 语法?

Python - 创建一个 "scripting"系统

ruby - 数组转换为哈希

ruby - 如何像在 Prime 类中一样在 Ruby 中创建默认实例?

Haskell ASCII 代码

javascript - 将路由器配置放在 Aurelia 的单独文件中

javascript - 评估黑魔法失去范围

ruby-on-rails - 从 Ruby 对象数组生成键值 JSON 对象

ruby-on-rails - Rails 4. 模型中的国家/地区验证