Problem using OpenStruct with ERB

前端 未结 4 1805
旧时难觅i
旧时难觅i 2020-12-16 14:32

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

EDIT 2: just updated to v1.9.1, patch 429, a

相关标签:
4条回答
  • 2020-12-16 15:13

    Fix to Problem:

    I stumbled upon this question when encountering the same type of error with similar code in Ruby 1.9.2.

    I'm new to Ruby so I can't explain what is happening. I continued to search online and found this blog post that has an approach that seems to work. After modifying your example to incorporate this approach I end up with 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 is run thru the 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
    

    0 讨论(0)
  • 2020-12-16 15:18

    What's your environment look like? This code worked for me (I just changed the string "bar" to "baz" to disambiguate 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
    

    Under 1.8.7 on OSX:

    defeateds-MacBook-Pro:Desktop defeated$ ruby -v
    ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0]
    
    0 讨论(0)
  • 2020-12-16 15:20

    The problem is where the binding is being executed. The 1.8.7-way obj.send(:binding) does not work anymore (see issue2161), the environment must be the object itself. So 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
    

    More about this issue in this answer.

    0 讨论(0)
  • 2020-12-16 15:26

    Looks like this does not 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
    

    So it gives error but still works in 1.9.3 and all the versions below 1.9.3.

    0 讨论(0)
提交回复
热议问题