views:

1358

answers:

3

Hello!

I have an ERB template inlined into Ruby code:

require 'erb'

DATA = {
 :a => "HELLO",
 :b => "WORLD",
}

template = ERB.new <<-EOF
 current key is: <%= current %>
 current value is: <%= DATA[current] %>
EOF

DATA.keys.each do |current|
 result = template.result
 outputFile = File.new(current.to_s,File::CREAT|File::TRUNC|File::RDWR)
 outputFile.write(result)
 outputFile.close
end

I can't pass the variable "current" into the template.

The error is:

(erb):1: undefined local variable or method `current' for main:Object (NameError)

How do I fix this?

+2  A: 

I can't give you a very good answer as to why this is happening because I'm not 100% sure how ERB works, but just looking at the ERB RDocs, it says that you need a binding which is a Binding or Proc object which is used to set the context of code evaluation. Trying your above code again and just replacing result = template.result with result = template.result(binding) made it work.

I'm sure/hope someone will jump in here and provide a more detailed explanation of what's going on. Cheers.

EDIT: For some more information on Binding and making all of this a little clearer (at least for me), check out the Binding RDoc.

theIV
A: 

EDIT: This is a dirty workaround. Please see my other answer.

It's totally strange, but adding

current = ""

before the "for-each" loop fixes the problem.

God bless scripting languages and their "language features"...

ivan_ivanovich_ivanoff
I think this is because block parameters are not real bound variables in Ruby 1.8. This has changed in Ruby 1.9.
Vincent Robert
The default binding that ERB uses to evaluate the variables is the top level binding. Your variable "current" does not exist in the top level binding, unless you use it there first (assign a value to it).
molf
So, in Ruby 1.9 it won't work?
ivan_ivanovich_ivanoff
+3  A: 

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 %>
ivan_ivanovich_ivanoff