隐藏绑定中的顶级常量

时间:2016-05-10 10:59:57

标签: ruby binding constants scoping

我想在模板方法中隐藏ENV,这样如果请求的密钥在真实ENV中不存在,我就会引发错误。显然,我不想在其他地方隐藏常量 - 只是在特定方法(特定绑定)中。这甚至可能吗?

解释员: - 我知道Hash#fetch的存在,我一直都在使用它。但是,我想在生成配置文件的ERB模板中使用它。这个配置文件可能会被更多人触及,并不是每个人都熟悉返回nil缺少Hash密钥的Ruby行为。我也在研究一个系统,在这个系统中,配置不良(或直接的错误配置或对格式的误解)导致明显的生产故障。失败是操作员错误。因此,我想在该模板中建立一个会引起加薪的公约。此外,我有一个宝石,strict_env,已经做到了 - 但你必须记住使用STRICT_ENV而不仅仅是ENV,并且每个“你必须”声明这个特定的工作流程,在这个特定的情况下,为我提出了一个红旗,因为我想要更强大。我当然可以选择更严格的模板语言并使用该语言的逻辑来提高(例如,Mustache),但由于团队已经熟悉ERB,并且Rails认可ERB模板化的YML作为可行的配置方法(甚至虽然你可能不同意这一点,但如果我能坚持这个工作流程那就太好了。这就是为什么我想在本地改变ENV[]的行为。

2 个答案:

答案 0 :(得分:1)

ERB#result采用可选绑定:

require 'erb'

class Foo
  ENV = { 'RUBY_VERSION' => '1.2.3' }
  def get_binding
    binding
  end
end

template = "Ruby version: <%= ENV['RUBY_VERSION'] %>"

ERB.new(template).result
#=> "Ruby version: 2.1.3"

b = Foo.new.get_binding

ERB.new(template).result b
#=> "Ruby version: 1.2.3"

答案 1 :(得分:0)

当密钥不存在时,您可以使用ENV.fetch(key)加注。

除此之外,你可以创建一个类并委托给ENV,例如:

class Configuration
  def self.[](key)
    ENV.fetch(key)
  end
end

但是从#fetch而不是#[]引发错误更像Ruby,因为这与Hash的行为相同。

最后你可以使用补丁ENV,但这通常不是一件好事:

def ENV.[](key)
  fetch(key)
end

据我所知,你不能使用refinements本地化这个猴子补丁,因为ENV是一个对象,而不是一个类,它的类是Object。