Template in a Template


Okay, here is my situation: I have a template with a 3-column layout.
The first column is printed out in the template, and the following two
columns are generated by the controllers. It is often the case that
the controllers only fill up the middle column, and the last one
remains empty, though sometimes the last one is used.


left top
left bottom
<%= @content_for_layout %> ----------------

Expected output of controller

middle top
middle bottom
right top
right bottom

As you can see, it is a hassle to put the all of that info into every
single view when most of the time, only the middle top div is the one
that is changing.

So here is my question: For those actions that only need to change the
middle top div, can I somehow specify a template within my controller
that puts the output of that action’s view into that structure rather
than having to copy that structure into every view?

I hope that makes sense…


If I understand you correctly, you have a three column layout that

  • fills in only two columns
  • fill in three columns

And the decision about how many to fill in is based on the action
(page, as you say).

If that’s the case then you can use the ‘layout’ command on a
controller by controller basis, with the :except and :only options to
do the switching that you need. You could have a layout called
‘layout_with_empty_column’ and ‘standard’ and the layout command in
your controller would choose appropriately.

If that’s not fine grained enough control (ie., you need to switch
based on data rather than simply the action) then I think you can
include :layout in your call to render. You would need to call render
explicitly (not just the default action/view name matching) to make
this work.

Thank you for your two suggestions.

I would prefer to avoid having two full templates. This would seem to
complicate the situation. I am trying to reduce the amount of code
that has to change if the template design were to change. I am trying
to minimize the amount of data spit out by each view so that I don’t
have to go through the tedious work of modifying every view.

It would be nice if I could catch the output of a particular action’s
view before it sends it to @content_for_layout in my layout file. I
could then take the output of that action, throw it inside my div
skeleton at the right spot, and then it could be passed onto the
layout file as @content_for_layout.

I suppose one way to approach this is to add more logic in the
template file that alters where @content_for_layout goes depending on
a class variable set per action…


Do you have an application layout defined?

I use the app layout to set the major parts (banner, left column, a
yield area, and the footer).

(app layout, abbreviated, also using haml, not erb notation)

#site-banner= “My App”
= render_partial ‘layouts/nav_ref_links’
- if current_user.is_admin?
= render_partial ‘layouts/admin_links’
= yield
= render_partial ‘layouts/footer_user’

In the middle of that template is the yield for the current page’s
content (which is the middle “column” of data), and the current page
determines whether it uses the third column or not (which it invokes as
a partial). So the pages that do show that third column just include a
“= render_partial ‘layouts/relateds’” call, others don’t. Not much
clutter there, and for the parts that don’t change often, fragment
caching works great.