I have an ERB template inlined into Ruby code:
require \'erb\'
DATA = {
:a => \"HELLO\",
:b => \"WORLD\",
}
template = ERB.new <<-EOF
As others said, to evaluate ERB with some set of variables, you need a proper binding. There are some solutions with defining classes and methods but I think simplest and giving most control and safest is to generate a clean binding and use it to parse the ERB. Here's my take on it (ruby 2.2.x):
module B
def self.clean_binding
binding
end
def self.binding_from_hash(**vars)
b = self.clean_binding
vars.each do |k, v|
b.local_variable_set k.to_sym, v
end
return b
end
end
my_nice_binding = B.binding_from_hash(a: 5, **other_opts)
result = ERB.new(template).result(my_nice_binding)
I think with eval
and without **
same can be made working with older ruby than 2.1
Got it!
I create a bindings class
class BindMe
def initialize(key,val)
@key=key
@val=val
end
def get_binding
return binding()
end
end
and pass an instance to ERB
dataHash.keys.each do |current|
key = current.to_s
val = dataHash[key]
# here, I pass the bindings instance to ERB
bindMe = BindMe.new(key,val)
result = template.result(bindMe.get_binding)
# unnecessary code goes here
end
The .erb template file looks like this:
Key: <%= @key %>
In the code from original question, just replace
result = template.result
with
result = template.result(binding)
That will use the each block's context rather than the top-level context.
(Just extracted the comment by @sciurus as answer because it's the shortest and most correct one.)
This article explains this nicely.
http://www.garethrees.co.uk/2014/01/12/create-a-template-rendering-class-with-erb/