使用OpenBtruct和ERB时出现问题

Der*_*ley 15 ruby binding erb nameerror

编辑:忘了包含我的环境信息... 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)
Run Code Online (Sandbox Code Playgroud)

此代码生成以下错误:

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 `'

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

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

tok*_*and 19

问题是正在执行绑定的位置.1.8.7方式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
Run Code Online (Sandbox Code Playgroud)

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


Mat*_*att 4

解决问题:

当我在 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)
Run Code Online (Sandbox Code Playgroud)

附加信息:

当代码通过 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)
=> #<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
Run Code Online (Sandbox Code Playgroud)