0

I'm learning ruby template and looking at the example provided by ruby documentation.

require 'erb'
x = 42
template = ERB.new <<-EOF
   The value of x is: <%= x %>
EOF
puts template.result(binding)

When I change the example by doing something like this:

require 'erb'
x = 42
template = ERB.new <<-EOF
   The value of x is: <%= x %>
   The value of y is <%= y %>
EOF
puts template.result(binding)

I was hoping the template will become something like this:

The value of x is: 42
The value of y is <%= y %>

It gives me the error:

Error: undefined local variable or method `y' for main:Object (NameError)

Looks like we need to pass all the values for all the variable substitutions in the template.

Question: I'm just wondering if it is possible that we can have two variable substitutions in the template but only pass one value into the template when binding the data?

2
  • You can check if a variable is defined with defined?(y). Commented Jul 24, 2018 at 12:14
  • @JagdeepSingh, what I was trying to say is that I have to always define the variables(x and y in this case) even I want the template result in "The value of x is: 42 The value of y is <%= y %>" ? Commented Jul 24, 2018 at 12:32

1 Answer 1

2

You can use double opening %%s to prevent it from being evaluated in erb.

This solution might look ugly but it returns exactly what you want (if it is what you want):

require 'erb'

template = ERB.new <<-EOF
  The value of x is: <% if defined?(x) %><%= x %><% else %><%%= x %><% end %>
  The value of y is: <% if defined?(y) %><%= y %><% else %><%%= y %><% end %>
EOF
 => #<ERB:0x00007feeec80c428 @safe_level=nil, @src="#coding:UTF-8\n_erbout = +''; _erbout.<<(-\"  The value of x is: \");  if defined?(x) ; _erbout.<<(( x ).to_s);  else ; _erbout.<<(-\"<%= x %>\");  end ; _erbout.<<(-\"\\n  The value of y is: \"\n);  if defined?(y) ; _erbout.<<(( y ).to_s);  else ; _erbout.<<(-\"<%= y %>\");  end ; _erbout.<<(-\"\\n\"\n); _erbout", @encoding=#<Encoding:UTF-8>, @frozen_string=nil, @filename=nil, @lineno=0> 

puts template.result(binding)
  The value of x is: <%= x %>
  The value of y is: <%= y %>
 => nil 

x = 20

puts template.result(binding)
  The value of x is: 20
  The value of y is: <%= y %>
 => nil 

y= 50

puts template.result(binding)
  The value of x is: 20
  The value of y is: 50
 => nil 

I assume you can do the formatting.

Sign up to request clarification or add additional context in comments.

2 Comments

Will behave as specified, but the implementation is... wordy :)
Can't help it. :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.