A problem about replacing a string in a template

File 1: test.tpl

Hello,#{name}!

File 2: test.rb

name = “jack”
f = File.open(“test.tpl”)
puts f.read
puts “Hello,#{name}”
f.close

And the result is:
Hello,#{name}!
Hello,jack!

How to change the “#{name}” to “jack”?

2006/12/25, Kuang D. [email protected]:

f.close

And the result is:
Hello,#{name}!
Hello,jack!

How to change the “#{name}” to “jack”?

puts eval f.read

Kuang D. wrote:

f.close

And the result is:
Hello,#{name}!
Hello,jack!

How to change the “#{name}” to “jack”?

Use ERB to do templating!

File 1: test.tpl

Hello, <%= name %>!

File 2: test.rb

require ‘erb’

name = “Jack”
File.open(‘test.tpl’) { |file| puts ERB.new(file.read).result }

Bye.
Andrea

Andrea F. wrote:

Use ERB to do templating!
File 2: test.rb

require ‘erb’

name = “Jack”
File.open(‘test.tpl’) { |file| puts ERB.new(file.read).result }

The above won’t quite work; you need to pass in the binding to use
local variables from the current scope.

Here’s one that does work, and slightly shorter, to boot:

File1: hello.tpl
Hello <%=name%>

File2: test.rb
require ‘erb’
name = “Jack”
puts ERB.new( IO.read( ‘hello.tpl’ ) ).result( binding )

On Dec 25, 2006, at 3:20 AM, Kuang D. wrote:

f.close

And the result is:
Hello,#{name}!
Hello,jack!

How to change the “#{name}” to “jack”?

AFAIK, the Ruby #{…} substitution facility only works when a string
literal is evaluated and converted into a String object. Therefore,
to do what you want using #{…} substitution, you will need to build
a double-quoted string from the template file contents and then
evaluate that string. For example:

File.open('/tmp/test.tpl', 'w') do |f| f.write 'Hello, #{name}!' end

name = “Jack”
File.open("/tmp/test.tpl") do |f|
puts eval(’"’ + f.read + ‘"’)
end

However, you might also consider a different approach. Define your
own template format and use String#gsub or String#gsub! to do the
replacement.

File.open('/tmp/test.tpl', 'w') do |f| f.write 'Hello, #name#!' end

File.open("/tmp/test.tpl") do |f|
puts f.read.gsub(’#name#’, ‘Jack’)
end

In the above example, I could have used String#sub instead of gusb
since there was only one substitution to be made.

Regards, Morton

Phrogz wrote:

The above won’t quite work; you need to pass in the binding to use
local variables from the current scope.

It works, please test it. In fact, If you don’t pass explicity the
binding argument, then the TOPLEVEL_BINDING is passed by default.

Andrea


Andrea F. @ Alca Societa’ Cooperativa
Servizi di Informatica Libera

Lecce - Italy
http://alca.le.it/

Phrogz wrote:

Andrea F. wrote:

It works, please test it. In fact, If you don’t pass explicity the
binding argument, then the TOPLEVEL_BINDING is passed by default.

Hrm, I did test it before I posted, albeit not exactly the code you
pasted.

I just tested your original code exactly, and it gave me the same
error. I’m using:
[sliver:~] gkistner$ ruby -v
ruby 1.8.5 (2006-08-25) [powerpc-darwin8.7.0]

What version of Ruby are you using that’s working for you?

Phrogz wrote:

I just tested your original code exactly, and it gave me the same
error. I’m using:
[sliver:~] gkistner$ ruby -v
ruby 1.8.5 (2006-08-25) [powerpc-darwin8.7.0]

What version of Ruby are you using that’s working for you?

I’m using:

andrea@ganimede:~$ ruby -v
ruby 1.8.4 (2005-12-24) [powerpc-linux]

Hmm… why it works for me?? :slight_smile:


Andrea F. @ Alca Societa’ Cooperativa
Servizi di Informatica Libera

Lecce - Italy
http://alca.le.it/

Andrea F. wrote:

Phrogz wrote:
It works, please test it. In fact, If you don’t pass explicity the
binding argument, then the TOPLEVEL_BINDING is passed by default.

Hrm, I did test it before I posted, albeit not exactly the code you
pasted. Here’s what I tested:

template = “Hello <%=name%>”
name = “Andrea”

require ‘erb’
puts ERB.new( template ).result
#=> NameError: undefined local variable or method `name’ for
main:Object

puts ERB.new( template ).result( binding )
#=> “Hello Andrea”

Am I mistaken? Is this substantively different from what you wrote, and
I’m missing something?

On Dec 25, 2006, at 2:39 PM, Andrea F. wrote:

I’m using:

andrea@ganimede:~$ ruby -v
ruby 1.8.4 (2005-12-24) [powerpc-linux]

Hmm… why it works for me?? :slight_smile:

I’m pretty sure ERb was changed in this recently.

James Edward G. II

Andrea F. wrote:

andrea@ganimede:~$ erb1.8 --version
erb.rb [2.0.4 2005/02/12]

Which version of erb are you using Phrogz?

[sliver:~] gkistner$ which erb
/usr/local/bin/erb

[sliver:~] gkistner$ erb --version
erb.rb [2.0.4 2006/02/12]

So, nominally the same version. Perhaps a change in binding/scope for
Ruby 1.8.5 vs 1.8.4?

Phrogz wrote:

So, nominally the same version. Perhaps a change in binding/scope for
Ruby 1.8.5 vs 1.8.4?

Argh, I figured it out: I was using an old version of the Ruby script
runner with TextMate, and that was causing some weird scoping issue. I
just deleted the old Bundles I had lying around with the old runner,
and the new (sexy looking!) script runner has ERB/TOPLEVEL_BINDING
working as expected, in 1.8.5.

James Edward G. II wrote:

I’m pretty sure ERb was changed in this recently.

James Edward G. II

Ok, this is the erb’s version I’m using:

andrea@ganimede:~$ erb1.8 --version
erb.rb [2.0.4 2005/02/12]

Which version of erb are you using Phrogz?


Andrea F. @ Alca Societa’ Cooperativa
Servizi di Informatica Libera

Lecce - Italy
http://alca.le.it/