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"?

···

--
Posted via http://www.ruby-forum.com/.

puts eval f.read

···

2006/12/25, Kuang Dong <kuangdong@gmail.com>:

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"?

--
Gerardo Santana

Kuang Dong wrote:

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"?

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

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:

<code>
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
</code>

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

<code>
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
</code>

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

Regards, Morton

···

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

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"?

Andrea Fazzi 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 )

Phrogz wrote:

Andrea Fazzi 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.
  
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 Fazzi @ Alca Societa' Cooperativa
Servizi di Informatica Libera

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

Andrea Fazzi 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?

Phrogz wrote:

Andrea Fazzi 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:

Phrogz wrote:
  

Andrea Fazzi 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?

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 Fazzi @ Alca Societa' Cooperativa
Servizi di Informatica Libera

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

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

James Edward Gray II

···

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

Phrogz wrote:

Phrogz wrote:

Andrea Fazzi 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?

I'm using:

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

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

James Edward Gray II wrote:

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

James Edward Gray 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 Fazzi @ Alca Societa' Cooperativa
Servizi di Informatica Libera

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

Andrea Fazzi 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.