The problem of using OpenStruct with ERB

EDIT: forgot to include information about my environment ... Win7x64, RubyInstaller Ruby v1.9.1-p378

EDIT 2: Just updated to version 1.1.1, patch 429 and still getting the same error.

Edit 3: the same code works in Ruby v1.8.7, patch 249, works fine. therefore it is v1.9.1 which broke it, apparently.

I'm new to using ERB, and the samples I could find were ... ummm ... less than useful ... playing with ERB for about an hour, I got some basic examples that work (finally) but I have no idea why this does not work ...

require 'ostruct' require 'erb' data = {:bar => "bar"} vars = OpenStruct.new(data) template = "foo " erb = ERB.new(template) vars_binding = vars.send(:binding) puts erb.result(vars_binding) 

this code causes the following error:

  irb (main): 007: 0> puts erb.result (vars_binding)
 NameError: undefined local variable or method `bar 'for main: Object
         from (erb): 1
         from C: /Ruby/v1.9.1/lib/ruby/1.9.1/erb.rb: 753: in `eval '
         from C: /Ruby/v1.9.1/lib/ruby/1.9.1/erb.rb: 753: in `result '
         from (irb): 7
         from C: /Ruby/v1.9.1/bin/irb: 12: in ``

why does he look at the main:Object binding? I told him to use binding from OpenStruct by going to vars_binding

can someone fill me with why it doesn't work and help me make it work?

+15
ruby binding nameerror erb
Jul 14 2018-10-14T00:
source share
4 answers

To fix the problem:

I came across this question when faced with the same type of errors with similar code in Ruby 1.9.2.

I am new to Ruby, so I cannot explain what is happening. I continued to search the web and found this blog post that has an approach that seems to work. After changing your example, to include this approach, I get the following working code:

 require 'ostruct' require 'erb' class ErbBinding < OpenStruct def get_binding return binding() end end data = {:bar => "baz"} vars = ErbBinding.new(data) template = "foo <%= bar %>" erb = ERB.new(template) vars_binding = vars.send(:get_binding) puts erb.result(vars_binding) 



Additional Information:

When the code runs through IRB, I get:

 require 'ostruct' => true require 'erb' => true class ErbBinding < OpenStruct def get_binding return binding() end end => nil data = {:bar => "baz"} => {:bar=>"baz"} vars = ErbBinding.new(data) => #<ErbBinding bar="baz"> template = "foo <%= bar %>" => "foo <%= bar %>" erb = ERB.new(template) => #<ERB:0x2b73370 @safe_level=nil, @src="#coding:IBM437\n_erbout = ''; _erbout.concat \"foo \"; _erbout.concat(( bar ).to_s); _erbout.force_encoding(__ENCODING__)", @enc=#<Encoding:IBM437>, @filename=nil> vars_binding = vars.send(:get_binding) => #<Binding:0x2b6d418> puts erb.result(vars_binding) foo baz => nil 

sub>

+4
Feb 20 '11 at 0:10
source share

The problem is where the binding is done. 1.8.7-way obj.send(:binding) no longer works (see issue2161 ), the environment should be the object itself. Therefore use instance_eval :

 require 'ostruct' require 'erb' namespace = OpenStruct.new(:first => 'Salvador', :last => 'Espriu') template = 'Name: <%= first %> <%= last %>' ERB.new(template).result(namespace.instance_eval { binding }) #=> Name: Salvador Espriu 

Read more about this release in this answer .

+19
Nov 28 '11 at 9:26 a.m.
source share

What does your environment look like? This code worked for me (I just changed the string "bar" to "baz" to fix this problem in my brain and added it to the template):

 require 'ostruct' require 'erb' data = {:bar => "baz"} vars = OpenStruct.new(data) template = "foo <%= bar %>" erb = ERB.new(template) vars_binding = vars.send(:binding) puts erb.result(vars_binding) 

When I run it, I get:

 defeateds-MacBook-Pro:Desktop defeated$ ruby erb.rb foo baz 

In section 1.8.7 on OSX:

 defeateds-MacBook-Pro:Desktop defeated$ ruby -v ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0] 
+2
Jul 14 '10 at 0:28
source share

It doesn't seem to work with higher ruby ​​versions

with ruby ​​2.1.1

 [19] pry(main)> name = "samtoddler" => "Suresh" [20] pry(main)> template_string = "My name is <%= name %>" => "My name is <%= name %>" [21] pry(main)> template = ERB.new template_string => #<ERB:0x007fadf3491c38 @enc=#<Encoding:UTF-8>, @filename=nil, @safe_level=nil, @src="#coding:UTF-8\n_erbout = ''; _erbout.concat \"My name is \"; _erbout.concat(( name ).to_s); _erbout.force_encoding(__ENCODING__)"> [22] pry(main)> puts template.result NameError: undefined local variable or method `name' for main:Object from (erb):1:in `<main>' 

with ruby ​​1.9.3

 [2] pry(main)> name = "samtoddler" => "Suresh" [3] pry(main)> template_string = "My name is <%= name %>" => "My name is <%= name %>" [4] pry(main)> template = ERB.new template_string => #<ERB:0x007f9be2a1fdf8 @enc=#<Encoding:UTF-8>, @filename=nil, @safe_level=nil, @src= "#coding:UTF-8\n_erbout = ''; _erbout.concat \"My name is \"; _erbout.concat(( name ).to_s); _erbout.force_encoding(__ENCODING__)"> [5] pry(main)> puts template.result My name is samtoddler 

Thus, it gives an error, but it still works in 1.9.3 and in all versions below 1.9.3.

0
Feb 17 '15 at 11:14
source share



All Articles