使用OpenBtruct和ERB时出现问题

编辑:忘了包含我的环境信息… Win7x64,RubyInstaller Ruby v1.9.1-p378

编辑2:刚刚更新到v1.9.1,补丁429,仍然得到同样的错误。

编辑3:在Ruby v1.8.7,补丁249中运行相同的代码,工作正常。 显然,它打破了它的v1.9.1。

我是新手使用ERB,我能找到的样品……嗯……不太有帮助……在ERB玩了大约一个小时后,我得到了一些基本的例子(最后),但我有不明白为什么这不起作用……

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) 

此代码生成以下错误:

  irb(main):007:0> put erb.result(vars_binding)
 NameError:未定义的局部变量或main:Object的方法`bar'
        来自(erb):1
        来自C:/Ruby/v1.9.1/lib/ruby/1.9.1/erb.rb:753:在'eval'中
        来自C:/Ruby/v1.9.1/lib/ruby/1.9.1/erb.rb:753:在'结果'中
        来自(irb):7
        来自C:/Ruby/v1.9.1/bin/irb:12:in''

为什么看main:Object绑定? 我告诉它通过传入vars_binding来使用OpenStruct中的vars_binding

有人可以告诉我为什么它不起作用,并帮助我让它工作?

修复问题:

当遇到Ruby 1.9.2中类似代码的相同类型的错误时,我偶然发现了这个问题。

我是Ruby的新手,所以我无法解释发生了什么。 我继续在网上搜索,发现这篇博文有一个似乎有用的方法。 在修改您的示例以合并此方法后,我最终得到以下工作代码:

 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) 

附加信息:

当代码通过IRB运行时,我得到:

 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) => # template = "foo <%= bar %>" => "foo <%= bar %>" erb = ERB.new(template) => #, @filename=nil> vars_binding = vars.send(:get_binding) => # puts erb.result(vars_binding) foo baz => nil 

问题在于执行绑定的位置。 1.8.7-way obj.send(:binding)不再起作用(参见issue2161 ),环境必须是对象本身。 所以使用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 

在这个答案中更多关于这个问题。

你的环境是什么样的? 这段代码对我有用(我只是将字符串“bar”更改为“baz”以消除我脑中的歧义,并将其添加到模板中):

 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) 

当我运行它时,我得到:

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

OSX下1.8.7以下:

 defeateds-MacBook-Pro:Desktop defeated$ ruby -v ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0] 

看起来这不适用于更高级的ruby版本

与ruby2.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 => #, @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 `
'

用ruby1.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 => #, @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 

所以它给出了错误,但仍然适用于1.9.3以及1.9.3以下的所有版本。

Interesting Posts