Layout tips using Ruby on Rails

When you don't need a sidebar

One issue I encountered with using my approach to Rails layout is when my template doesn't have a sidebar. Since I have already defined a 'div' tag for the sidebar in the layout file, the generated HTML page will have an empty 'div' tag. If you use CSS (you use CSS, right?), a border for example to the 'div' sidebar tag, you will have a hanging horizontal bar in your output. Another issue when I want the 'main' content to occupy
the whole width of the page.

My solution is to have a condition for the 'sidebar' in the layout file and let each template specify the condition.

HTML:
  1. <!-- layout file -->
  2.  
  3. <% unless @wide_screen %>
  4.  <div id="sidebar">
  5.    <div class="content">
  6.      <%= yield :sidebar %>
  7.    </div> <!-- content -->
  8.  </div>  <!-- secondary -->
  9. <% end %>
  10.  
  11. <!-- template file that has no sidebar -->
  12.  
  13. <%
  14.  @page_id = 'No sidebar'
  15.  @wide_screen = 'wide'
  16. %>
  17.  
  18. <% content_for('main') %>
  19.  Dynamic main content.
  20. <% end %>

I use the value of the '@wide_screen' variable as a class attribute of the 'body' tag. Then, I use CSS to expand the 'main' content as necessary.

CSS:
  1. #main {
  2.   width: 75%;
  3. }
  4.  
  5. body.wide #main {
  6.  width: 100%;
  7. }

A layout for everything

Everytime you use scaffold, a layout file is generated along with your controller. If the name of your controller is 'EmployeesController', the layout file is 'employees.rhtml'. This is the default setup but a typical web app would use a single layout for most, if not all, controllers. There are several ways to specify the layout to be used in your application.

1. Specify each layout in your controller

RUBY:
  1. class AccountController <ApplicationController
  2.   layout 'employees'
  3. end

This tells Rails to use the layout 'employees.rhtml' for all templates used by 'AccountController'. You can also use this technique to allow themes - a common requirement in content management systems. You can have one controller that handles read-access to data by any users. The public display can then be changed to a different theme by an authorized user (handled by a another controller). In your controller, dynamically specify the layout to be used.

RUBY:
  1. class ViewController <ApplicationController
  2.   layout :template
  3.  
  4.   def template
  5.       # return the layout to be used
  6.   end
  7. end

2. Specify the layout in your application controller.

RUBY:
  1. class ApplicationController <ActionController::Base
  2.   layout 'employees'
  3. end

This tells all controllers to use the layout specified in your application controller. However, this will not work if there is a layout file for the controller, or there is a layout specified inside the controller (approach #1).

3. Create an application layout

If you don't like specifying the layout in the application controller, you can define the layout 'application.rhtml'. Again, this will not be used if a layout is already defined for the controller either via a layout file or the layout method.

4. Specify layout for each render

The 'render' method uses the layout specified in the controller. If you want to use a different layout in your action, just pass the ':layout => "employees"' parameter.


Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically each day to your feed reader. If you don't have a feed reader, you can always have these articles delivered to your email inbox every day. Click here to sign up.

Trackbacks & Pingbacks

No trackbacks/pingbacks yet.

Comments

oohh.. interesting.. a Pinoy’s blog featuring RoR!

good thing there’s at least one person in the philippines who knows what he’s doing. much better than the dumbass found at http://jpatambag.blogspot.com/

Hi Nightfox,

Hope you find my posts useful.

Hi Raichu,

Thanks for the appreciation. I hope you and ‘jpatambag’ are not enemies :)

Raichu, for God’s sake be careful calling people dumbass…. or try not to.

Personally, I use the render method quite a lot. I often find it necessary to render a specific template for certain actions in a controller where the controller layout wouldn’t make sense.

Nice articles on the layout, how about a few on custom form builders? Damn, I hate them forms but they are the bread and butter of web development. Bonus points for a custom form builder that renders for multiple models in a single form =)

hello, just visiting :) nice site. (saw you at itech) :D

Jose: Thanks for dropping by. Don’t forget to learn Ruby on Rails :)

Raymond: Thanks man. I haven’t tried form builders yet but I will surely write a tutorial once I get the hang of it.

Nice post, Greg.

In keeping with the spirit of convention-over-configuration, I think it would be more practical to scrap the content_for (’main’) part, and just rather use the default render space (i.e. yield :layout in your layout) to put the main contents of the page.

Hi there

I was pointed here from the ruby mailing list, but sadly it doesn’t answer my questions… Maybe you could take a look at it?
http://www.ruby-forum.com/topic/103631
Thanks. :-)

Awesome although I don’t normally employ this technique. It may as well be more useful in other applications in the future.

I like adding classes to the body tag to drive things from special css for the entire page to menu highlighting. You mention that you use this method as well (right above your css above) but you don’t say HOW. I’d love to know…

Hi Lorin,

I have this code in the layouts/admin.rhtml

@page_id, :class => @screen_size}.stringify_keys) %> >

Then, in the template, I specify the value of @screen_size.

< % @screen_size = 'wide' %>

Hi Greg,

thanks for the great insight into layout. I was wondering if we can use session identification in layouts. For example,
then show navigation links: A ELSE show navigation links B .

Forgive me about the syntax :) just for the sake of understanding.

I tried this approach but i am getting an error that you have not spcified ‘nil’ user type. It would be great if you can guide me on this.

Thanks.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>


*
To prove you're a person (not a spam script), type the security word shown in the picture.
Anti-Spam Image