15

編集:環境情報を含めるのを忘れていました... Win7x64、RubyInstaller Ruby v1.9.1-p378

編集 2: v1.9.1、パッチ 429 に更新されたばかりで、同じエラーが発生します。

編集 3: Ruby v1.8.7、パッチ 249 でこの同じコードを実行すると、正常に動作します。どうやらそれを壊したのはv1.9.1です。

私はERBを初めて使用し、見つけたサンプルは...うーん...役に立たない...ERBを約1時間いじって、いくつかの基本的な例が機能するようになりました(最終的に)が、なぜこれが機能しないのかわかりません...

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> puts erb.result(vars_binding)
NameError: main:Object の未定義のローカル変数またはメソッド「bar」
        から (erb):1
        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'
        から (irb):7
        C:/Ruby/v1.9.1/bin/irb:12:in から

なぜmain:Objectバインディングを見ているのですか?渡すことで、OpenStruct からのバインディングを使用するように指示しました。vars_binding

誰かがそれがうまくいかない理由を教えてくれますか?

4

4 に答える 4

19

問題は、バインディングが実行されている場所です。1.8.7-wayobj.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

この回答のこの問題についての詳細。

于 2011-11-28T09:26:24.180 に答える
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)

追加情報:

コードが 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

于 2011-02-20T00:10:34.717 に答える
2

あなたの環境はどのように見えますか?このコードは私にとってはうまくいきました(文字列「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]
于 2010-07-14T00:28:24.040 に答える