ERB: import function

A

Alvaro Bautista

I want to import rhtml files into another using ERB. I wrote a function:

def import(fn)
e = ""
File.open(fn) do |f|
e = ERB.new(f.read)
end
e.result
end

This function does what I want, reads the template file and processes it
returning the result string.

The problem is that if I do, for instance:

<html>
<body>
Some content
<%= import('some.rhtml') %>
</body>
</html>

The result contains only the some.rhtml processed file and the content
following the import line.
 
R

Ryan Davis

def import(fn)
e = ""
File.open(fn) do |f|
e = ERB.new(f.read)
end
e.result
end

I can't help you with your actual problem, but I can suggest how to
simplify the code:

def import path
ERB.new(File.read(path)).result
end

I doubt that'll have any impact on the problem at hand, and it won't
affect the performance by much, but it is entirely comprehensible at a
glance and I think that counts for a lot.
 
J

Jano Svitok

I can't help you with your actual problem, but I can suggest how to
simplify the code:

def import path
ERB.new(File.read(path)).result
end

This is halfway to solution:

def import path
ERB.new(File.read(path), nil, nil, '_x_').result()
end

Notice the other parameters, especially the last one. ERB uses one
variable to store the output. If you don't specify any,
it will use a default one - and each nested ERB will overwrite the new
one. The solution is 1. use another name for each nested import
2. use another binding for each nested import (i.e. make another
scope, and let ERB create another var with the same name
in the new scope/binding, leaving the ability to return to the previous one)

I'll leave the details for your homework ;-)

http://ruby-doc.org/core/classes/ERB.html#M002827

Jano
 
A

Alvaro Bautista

Jano said:
This is halfway to solution:

def import path
ERB.new(File.read(path), nil, nil, '_x_').result()
end

Notice the other parameters, especially the last one. ERB uses one
variable to store the output. If you don't specify any,
it will use a default one - and each nested ERB will overwrite the new
one. The solution is 1. use another name for each nested import
2. use another binding for each nested import (i.e. make another
scope, and let ERB create another var with the same name
in the new scope/binding, leaving the ability to return to the previous
one)

I use the last parameter to put the output in a variable an it works.

Thank you.
 
J

James Masters

Jano said:
def import path
ERB.new(File.read(path), nil, nil, '_x_').result()
end

If you are planning on recursive inclusion, then you might want to add
some kind of a unique number to the output variable to avoid collision:

class ERB
@output_num = 0
class << self
attr_accessor :eek:utput_num
end
end

def import path
n = ERB.output_num += 1
ERB.new(File.read(path), nil, nil, '_x_'+n.to_s).result()
end

One thing to also be careful with is that when a syntax error occurs,
the file name is not printed in the exception message. It might be
useful to rescue the syntax error exception and include the file name in
the exception stack.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,183
Latest member
OrderGlycoEase

Latest Threads

Top