I have a Rails-based site with a basic two-column layout. On the right is a sidebar with different (let’s just say) vertical widgets. Depending on what page you visit, the widgets can be included, excluded, and in different order. For ex:
Main Page (Application)
PAGE CONTENT…
SIDEBAR
- Widget A
- Widget B
- Widget C
Page X
PAGE CONTENT…
SIDEBAR
- Widget D
- Widget A
- Widget C
Page Y
PAGE CONTENT…
SIDEBAR
- Widget E
- Widget A
- Widget B
- Widget C
Right now the way that I’m displaying the page-specific widgets is not very DRY. I’m creating a layout for each page, then copying and pasting the same HTML partials and widget partials over and over. For ex:
application.html.erb
<%= render :partial => 'shared/html_header' %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<%= render :partial => "shared/head" %>
<body>
<div id="outer">
<%= render :partial => 'shared/banner' %>
<%= render :partial => 'shared/nav' %>
<div id="main">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;">
<tr style="vertical-align:top;">
<td style="width:759px;">
<%= render :partial => 'shared/content' %>
</td>
<td><%= image_tag("spacer.gif", :width => "5") %></td>
<td style="width:252px;">
<%= render :partial => 'shared/widget_a' %>
<%= image_tag("spacer.gif", :height => "10") %>
<%= render :partial => 'shared/widget_b' %>
<%= image_tag("spacer.gif", :height => "10") %>
<%= render :partial => 'shared/widget_c' %>
<%= image_tag("spacer.gif", :height => "10") %>
</td>
</tr>
</table>
</div>
<%= render :partial => 'shared/footer' %>
</div>
<%= render :partial => 'shared/user_voice_widget_script' %>
<%= render :partial => 'shared/google_analytics_script' %>
</body>
</html>
I basically just repeat this pattern for the other page layouts, but with the page-specific widgets. Doesn’t seem too DRY.
I’m thinking there has to be a more efficient way to do this. Any suggestions?
You can use a single layout file which defines the two column structure for all your pages and then use Rail’s
content_forhelper to contextually populate your sidebar, depending on the page visited. Then the only page specific information is the sidebar detail, not the whole layout being repeated over and over.In your (single) application layout:
Somewhere in your pages:
If enough of the widget combinations occur frequently together you could consider putting their
renderdirectives together into partials and using those in yourcontent_forblock.The general technique is described here