# Insert into erb binding

**URL:** <https://www.ruby-forum.com/t/insert-into-erb-binding/78636>\
**Category:** Ruby\
**Created:** [December 7, 2006, 12:12pm UTC](https://www.ruby-forum.com/t/insert-into-erb-binding/78636 "2006-12-07T12:12:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![nuby2ruby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/54ee81/32.png) [@nuby2ruby](https://www.ruby-forum.com/u/nuby2ruby)\
**Post date:** [December 7, 2006, 12:12pm UTC](https://www.ruby-forum.com/t/insert-into-erb-binding/78636/1 "2006-12-07T12:12:25Z")

</div>

I have a class that takes a template, parses it through ERB, then takes  
the output for some custom manipulation. When the class is created as an  
object a binding is passed to it to be passed to the template. Is it  
possible to get the class to insert a variable into the binding?  
Example:

Template:  
\<%=@variable1%\> \<%=variable2%\>

class:  
class Renderer  
def initialize(template\_file, apply\_binding)  
@file = template\_file  
@binding = apply\_binding  
end

```
def render
   @variable2 = "There"

   template = ERB.new(File.read(@file))
   template_results = template.result(@binding)

   # Perform on template results
end

```

end

Program:  
@variable1 = “Hello”  
renderer = Renderer.new(‘template.xml’, binding)  
renderer.render

current output: Hello  
desired output: Hello There

So I want the renderer class to add @variable2 to the binding before  
calling the template.

–

_Jeremy W._

---

<div class="post-metadata">

**Author:** ![nuby2ruby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/54ee81/32.png) [@nuby2ruby](https://www.ruby-forum.com/u/nuby2ruby)\
**Post date:** [December 7, 2006, 1:12pm UTC](https://www.ruby-forum.com/t/insert-into-erb-binding/78636/2 "2006-12-07T13:12:33Z")

</div>

On 12/7/06, Jeremy W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> def initialize(template_file, apply_binding)
> # Perform on template results
> 
> ```
> 
> So I want the renderer class to add @variable2 to the binding before  
> calling the template.

IIRC this is (more or less) from Rails code:

```
    def evaluate_locals(local_assigns = {})
            b = binding
            local_assigns.each { |key, value| eval "#{key} =

```

local\_assigns["#{key}"]", b }  
b  
end

The trick is to use eval with binding as an additional argument.

---

<div class="post-metadata">

**Author:** ![nuby2ruby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/54ee81/32.png) [@nuby2ruby](https://www.ruby-forum.com/u/nuby2ruby)\
**Post date:** [December 8, 2006, 11:28am UTC](https://www.ruby-forum.com/t/insert-into-erb-binding/78636/3 "2006-12-08T11:28:18Z")

</div>

surely this won’t work as the binding in my case is coming from an  
external source, so the ruby in the eval won’t have access to the  
variable in the render method?

Jan S. wrote:

> > class:  
> > template\_results = template.result(@binding)  
> > current output: Hello  
> > local\_assigns["#{key}"]", b }  
> > b  
> > end
> 
> The trick is to use eval with binding as an additional argument.

–

_Jeremy W._  
Serval Systems Ltd.

[www.servalsystems.co.uk](http://www.servalsystems.co.uk) [http://www.servalsystems.co.uk](http://www.servalsystems.co.uk)  
Tel: 01342 331940  
Fax: 01342 331950

---

<div class="post-metadata">

**Author:** ![nuby2ruby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/54ee81/32.png) [@nuby2ruby](https://www.ruby-forum.com/u/nuby2ruby)\
**Post date:** [December 8, 2006, 5:13pm UTC](https://www.ruby-forum.com/t/insert-into-erb-binding/78636/4 "2006-12-08T17:13:10Z")

</div>

Ah ok, I get it but here is the problem, which I didn’t specify…  
@variable2 doesn’t hold static data, it holds an object, which is  
created in the render method like so:

def render  
@variable2 = Object.new  
eval(“@variable2 = ???”, @binding)

That’s what I meant by the variable not being in the binding, thus not  
accessible to eval.

Jan S. wrote:

> some\_binding), the variable @var will be set in that binding.  
> TEMPLATE = “\<%=@variable1%\> \<%=@variable2%\>”
> 
> end

–

_Jeremy W._  
Serval Systems Ltd.

[www.servalsystems.co.uk](http://www.servalsystems.co.uk) [http://www.servalsystems.co.uk](http://www.servalsystems.co.uk)  
Tel: 01342 331940  
Fax: 01342 331950

---

<div class="post-metadata">

**Author:** ![nuby2ruby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/54ee81/32.png) [@nuby2ruby](https://www.ruby-forum.com/u/nuby2ruby)\
**Post date:** [December 8, 2006, 3:08pm UTC](https://www.ruby-forum.com/t/insert-into-erb-binding/78636/5 "2006-12-08T15:08:43Z")

</div>

On 12/8/06, Jeremy W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> surely this won’t work as the binding in my case is coming from an  
> external source, so the ruby in the eval won’t have access to the  
> variable in the render method?

So once more: The trick is to use eval with binding as an additional  
argument.  
That means when eval gets a binding as the second argument, it will  
operate  
in that context. In this case, if you eval(“@var = 123”,  
some\_binding), the variable @var will be set in that binding.

Beware that you are modifying the original binding, so you might  
corrupt the original caller.  
Maybe @binding = apply\_binding.dup will be neccessary.

(I added @ in the template - it was missing)

require ‘erb’

# TEMPLATE = “\<%=@variable1%\> \<%=variable2%\>”

TEMPLATE = “\<%=@variable1%\> \<%=@variable2%\>”

class Renderer  
def initialize(template\_file, apply\_binding)  
@file = template\_file  
@binding = apply\_binding  
end

```
def render
    # @variable2 = "There"
    eval("@variable2 = \"There\"", @binding)

    # template = ERB.new(File.read(@file))
    template = ERB.new(TEMPLATE)

    template_results = template.result(@binding)

    # Perform on template results

template_results
end

```

end

require ‘test/unit’

class TestERB \< Test::Unit::TestCase  
def test\_variable  
@variable1 = “Hello”

```
	renderer = Renderer.new('template.xml', binding)
	assert_equal "<xml>Hello There</xml>", renderer.render
end

```

end
