Subtemplating with ERB

Hey!

I’m using Ruby withour Rails, but i make use of the ERB-template
functionality. So i think is a good place to post this one here.

I want to do subtemplating, is that possible?

E.g. I have a index.rhtml file.
In this file i have html code combined with some ruby fragments and in
addition i want to include subtemplates, how do i do that?:

<%= header %>

<% # include subtemplate.rhtml here! %>

</body

thx

On Nov 28, 2007 9:54 AM, Christian K.
[email protected] wrote:

addition i want to include subtemplates, how do i do that?:

In rails the concept you are looking for is a partial template. As
usual there are conventions to follow.

Partials have file names starting with an underscore. So the filename
would be _subtemplate.rhtml rather than just subtemplate.rhtml.

Then:

<%= render :partial => ‘subtemplate’ %>

where you want to include it.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Wed, Nov 28, 2007 at 10:13:01AM -0500, Rick DeNatale wrote:

On Nov 28, 2007 9:54 AM, Christian K.
[email protected] wrote:

Hey!

I’m using Ruby withour Rails, but i make use of the ERB-template
functionality. So i think is a good place to post this one here.

I want to do subtemplating, is that possible?
[…]

where you want to include it.

Christian, you are better off asking this on the ruby-talk mailing list
rather than on the Rails list, since you are much more likely to get
help
with a non-Rails use of ERB. You’re probably going to mostly get
responses
that talk about render :partial, as above, on this list.

Rick DeNatale
–Greg

On Nov 28, 2007 9:54 AM, Christian K.
[email protected] wrote:

addition i want to include subtemplates, how do i do that?:

<%= header %>

<% # include subtemplate.rhtml here! %>

This is actually somewhat tricky. Rails does a lot for you in this area.

Here’s something to get you started:

<%= ERB.new(IO.read(‘subtemplate.rhtml’), nil, nil, ‘_erbout2’).result
%>

What ERB does is to take your template and turn it into pure Ruby code
that builds up a string using a variable name called (by default)
‘_erbout’. When you call result(), the ruby code is eval’d in the
context of the binding passed (or TOPLEVEL_BINDING if no binding is
passed).

To do a sub-template, you need to eval the sub-template and insert
it’s results mid-stream. But all the eval-ing happens at once (when
you do the outermost template), so you need to use a different output
variable name in your subtemplate, or your subtemplate will stomp on
the output of your outer template. Hence the ‘_erbout2’ parameter to
new(). If the subtemplate called yet another subtemplate, you would
need another variable name, and so forth, for each level of nesting.

Bob S. wrote:

Here’s something to get you started:

<%= ERB.new(IO.read(‘subtemplate.rhtml’), nil, nil, ‘_erbout2’).result
%>

i created two templates:

toplevel_template.rhtml:

<%= header %>

<%= ERB.new(IO.read('sublevel_template.rhtml'), nil, nil, '_erbout2').result %>

sublevel_template.rhtml:

<%= header2 %>

in Ruby I execute this code to setup the values:

template = ERB.new(File.read(‘toplevel_template.rhtml’))

set vars

header = “Welcome”
header2 = “Header”

create page

page = template.result(binding())

But i get the error: undefined local variable or method `header2’ for
main:Object

What is wrong here?

thx ck

I have the same problem.
I am translating an old ASP-application (pre dot.net) that uses textual
includes to implement DRY.
When I try to use ERB for this I get scoping problems

  • Variables or functions declared in the subtemplate I try to read with
    erb are not ‘remembered’ when returning to the main view (that did the
    erb call)

Note. if a variable was declared the first time in the main view it is
possible to change the value of that variable in the subtemplate and
that new value is ‘remembered’.

I can’t see how you can implement good DRY-solution in ruby/rails given
the above problem but it should be possible since ruby/rails is a much
newer/more modern framework than old asp.

Of course you can put the methods in an helper method but then you don’t
have access to the <% %> tags and you don’t have access to variables
declared in the view.

Very grateful for any help!

/Kristofer

Christo Karlson wrote:

I can’t see how you can implement good DRY-solution in ruby/rails given
the above problem but it should be possible since ruby/rails is a much
newer/more modern framework than old asp.

Of course you can put the methods in an helper method but then you don’t
have access to the <% %> tags and you don’t have access to variables
declared in the view.

As is was using ERB without Rails i made the switch to a template engine
called tenjin. There it’s possible to have clean subtemplate resolution.

Can’t be of any help regarding rails.

cheers kerthi

Yes I tested quite a bit with different renders and partials. What I
remembered was that it couldn’t asked the variables declared before the
render-statement. i.e. when you start rendering the subtemplate all the
variables from the main template are forgotten.

Of course one solution is to declare the variables with @varname in the
controller but I am working with a automatic translator from asp and I
would really need to have the code in the views for a start with a
subtemplating system that works just like a text-include (like in asp
with <–#include file)

Yikes. Good luck with that. :wink:

The only thing that comes to my mind is the :locals hash you can pass in
a call to render :partial. But it’d probably be as much of a pain to
figure out how to have your transliterator make those calls as it would
be to have it put variable creation code in the controllers…

I would think partials would serve you (laying out vars populated in the
appropriate controller).

Have you looked at those at all?