0
Posted September 6, 2012 by Spyros in Ruby on Rails
 
 

Use Template Inheritance to Create Dynamic Sidebars

sidebar-300x195
sidebar-300x195

A pretty standard problem that web developers have to face is about creating a dynamic sidebar in their application layouts. There are many different ways to achieve that effect, but most of them require some sort of repeatable code, like using content_for in all your views. This seems to repetitive for no real reason and so, after some thought, i decided that the most versatile way is to use the internal template inheritance that Rails provides in its views, coupled with a simple instance variable, in case a sidebar is not needed. But first things first, let’s define the problem.

In Need of a Dynamic Sidebar

What we would like to do is have a nice way to define whether we want a sidebar in our application or not. The problem that arises in such a situation is mostly about the HTML markup. A typical sidebar markup is like this :

<div class="row">
  <div class="span2" id='sidebar'></div>
  <div class="span10" id='content'></div>
</div>

This is the markup that is actually used with the well known twitter-bootstrap-rails gem. The whole content contains 12 ‘spans’. In this situation, the sidebar is 2 spans wide and the content is 10 spans wide. If we did not want to use a sidebar at all, we would have to remove the ‘sidebar’ div AND change the content class to ‘span12′.

Use Template Inheritance for the Basic Template

Ideally, our controller views should not contain any content_for or other repetitive methods, but just the view code. It’s important to know how you can use template inheritance, in order to not repeat yourself in your views. Simply, template inheritance is an order at which views are executed. The first place your controller searches for when it wants to render a view is in ‘views/controller_name’ folder. Therefore, if you have a users controller, the view that will be rendered will be the one in your ‘views/users’ folder. However, if the view does not exist in this folder, it will search for it in the ‘views/application’ folder. This is a great way to have a generic view in your application folder and only create a view specific one, in case you need different content.

Imagine the scenario about a left sidebar. Normally, most of the pages have a standard left sidebar. Thus, we would go about creating our left sidebar view in our application folder. Therefore, we create a file ‘views/application/_left_sidebar.html.erb’, with the contents :

<div class="span2">
  <ul class=''>
    <li>....</li>
    <li>....</li>
  </ul>
</div>

This now specifies our standard template for a left sidebar. Anytime we want to override it, we just need to create a ‘_left_sidedar.html.erb’ partial in our controller specified folder, like ‘views/users’ for our users_controller. There is one more thing left. That is the case when one of our controllers does not need to render a sidebar at all. There are different ways to go about this, but i prefer to have a defined?(@no_sidebar) instance variable. In case a controller specifies the @no_sidebar instance variable, the sidebar is not shown at all and the content captures 12 spans, instead of 10. Below is the controller code that instantiates the variable in a before_filter :

class HomeController < ApplicationController
  before_filter { @no_sidebar = true }
  .....

And finally, this is the application layout(found in ‘views/layouts’):


<% unless defined?(@no_sidebar) %>
  
  <%= render 'left_sidebar' %>
  <div class="span10" id="content">
    <%= yield :layout %>
  </div>
  
<% else %>

  <div class="span12" id="content">
    <%= yield :layout %>
  </div>
  
<% end %>

Spyros