2

我有一个使用GLI框架用 Ruby 编写的命令行实用程序。我想在我的主目录中配置我的命令行实用程序,使用 Ruby 本身作为 DSL 来处理它(类似于Gemfileor Rakefile)。

我在文件夹 lib/myapp 中的类 ConfigData 中。该类看起来像以下方式:

class ConfigData
  @@data = {}

  class ConfigItem
    def initialize
      @data = {}
    end
    def missing_method(name, *args)
      @data[name] = args[0]
    end
  end

  def self.add(section)
    item = ConfigItem.new()
    yield item
    @@data[section]=item
  end

end

现在,我想要的是配置文件,最好是 name Myappfile,在当前工作文件夹中,具有以下内容

add('section1') do |i|
  i.param1 'Some data'
  i.param2 'More data'
end

当此代码包含在ConfigDataclassendConfigData 之间时,它工作正常。但现在我想把它放在我启动应用程序的工作文件夹中。

class我在 ConfigData和ConfigData之间尝试了 require('./Myappfile') end,但它对我不起作用。我试图阅读 rake 的源代码,但对我来说不是很清楚。

任何提示如何解决这个问题?

4

1 回答 1

2

要在实例的上下文中评估代码,这是您想要做的,您需要该instance_eval()方法。永远不要使用正常的 eval。曾经。无论如何,这里是你如何加载你的 fingi 文件并获取数据:

config = ConfigData.new
config.instance_eval(File.read("Myconfig"))
#Access configuration data here from the config object

就这么简单。以这种方式加载对象后,您可以访问对象的值。

警告:这不是很安全。这实际上是一个巨大的安全漏洞。这是安全版本:

f = Fiber.new {str = File.read("Myconfig"); $SAFE = 4; config = ConfigData.new; config.instance_eval(str); Fiber.yield config}
confdata = f.resume
#Access configuration data here from confdata.

这在(某种)沙箱中执行外部代码,因此它不能做任何卑鄙的事情。


另外,你为什么不直接使用 YAML 配置?除非配置需要运行类似 RUBY_VERSION 的代码pwd或访问 RUBY_VERSION,否则 YAML 更简单、更安全,而且更防故障。

于 2012-12-23T15:08:37.313 回答