Rails Layouts on a Per-Method Basis
Written by steve on 11-12-2008 at 03:36 PM
Many Rails developers will create a default layout in application.html.erb and use it as a consistent wrapper for all pages rendered on a site. This is one of the cool features of Rails – consistent rendering of the site’s layout. But what if you want to change things for certain controllers or actions.
Layouts By Controller
This is the trivial case because all you need to do is:
<pre>
class AdminController < Application
layout 'admin'
and every action within AdminController uses admin.html.erb instead of application.html.erb. But how about a controller that handles some public-facing and some administrative aspects?
Layouts With Exceptions
At first blush, this would also appear to be trivial. Just modify the code above as follows:
<pre>
class AdminController < Application
layout 'admin', :only => [:some_action]
At first glance this is flawless, and of course you’re testing the action you changed, so you got suckered in. One day, you go to /some_public_facing_action and WTF?? There is no layout at all.
It turns out that what the line
layout ‘admin’, :only => [:some_action]really means is apply the ‘admin’ layout to some_action and don’t apply any layout to anything else. So you think, well, How’s about:
<pre>
class AdminController < Application
layout 'admin', :only => [:some_action]
Bzzzt! Wrong answer. Rails already believes the public facing action is exempt from layout.
Using More Than One Layout in A Controller
The best way I’ve found to do this is to write a helper that determines on an individual basis which methods require which layout. Here’s how:
<pre>
class AdminController < Application
layout :smart_layout
You may notice that I have only one action in my array, but more commonly, there will be multiple actions.
Further Reading
See Rails Guides for an in depth discussion of how layouts are inherited and controlled.
0 comments

