ERB: import function

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:

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

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

On Feb 12, 2008, at 3:48 PM, Alvaro B. wrote:

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.

On Feb 13, 2008 9:10 AM, Ryan D. [email protected] wrote:

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 :wink:

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

Jano

Jano S. wrote:

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.

Jano S. wrote:

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 :output_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.