I would like to shadow ENV
within a templating method, so that I can raise an error if keys are requested which are not present in the real ENV
. Obviously I don't want to shadow the constant elsewhere - just within a specific method (specific binding). Is this even possible?
Explainer: - I know about the existence of Hash#fetch
and I use it all the time and everywhere. However, I want to use this in an ERB template generating a config file. This config file is likely to be touched by more people than usual, and not everyone is familiar with the Ruby behavior of returning a nil
for a missing Hash key. I am also working on a system where, of late, configuration mishaps (or straight out misconfigurations, or misunderstandings of a format) caused noticeable production failures. The failures were operator error. Therefore, I would like to establish a convention, within that template only, that would cause a raise. Moreover, I have a gem, strict_env
, that does just that already - but you have to remember to use STRICT_ENV
instead of just ENV
, and every "you have to" statement for this specific workflow, in this specific case, raises a red flag for me since I want more robustness. I could of course opt for a stricter templating language and use that language's logic for raising (for example, Mustache), but since the team already has some familiarity with ERB, and Rails endorses ERB-templated-YML as a viable config approach (even though you might not agree with that) it would be nice if I could stick to that workflow too. That's why I would like to alter the behavior of ENV[]
locally.
ERB#result
takes an optional binding:
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"