7: All About Layouts
(view original Railscast)
This episode is all about layouts. Layouts are view files that define the code that surrounds a template. They can be shared across many actions and controllers.
Application layouts
The template below lists all of the projects.
<h2>Projects</h2>
<ul>
<% for project in @projects %>
<li><%= project.name %></li>
<% end %>
</ul>
This generates a fairly basic web page:
If we want to add, say, a header, a logo and some menu navigation to this site and have it visible on every page then we should use a layout. Layout files live in the /app/view/layouts folder of a Rails application. To create one, create a new file called application.rhtml[1] in the layouts folder. This will create a global layout which will be used by all controllers and all actions. Our application layout file looks like this.
<h1>Application Layout!</h1> <%= yield %>
The important line in the code above is the second one. The keyword yield tells the layout where to place the content for the template that is using the layout. Now, if we look again at the page above we can see that the layout has been added.
The layout is global, so it will be added to any action in any controller across the application. Most of the time this will be enough, but what if we need different layouts for different parts of our application?
Controller-specific Layouts
A layout can be made specific to a controller by giving it the name of the controller. So, to make a layout that will be used by all of the actions in the Projects controller create a file in the layouts folder called projects.rhtml[2]. This means that the layout will be used only by the projects controller.
<h1>Project Layout!</h1> <%= yield %>
What if we want to share a layout across a number of controllers, not just one, e.g. for an admin layout? Rails allows you to use the layout command to specify the name of the layout that should be used within a controller.
class ProjectsController < ApplicationController
layout "admin"
def index
@projects = Project.find(:all)
end
end
A layout specified with the layout commmand will override any controller-specific or application-specific layouts.
Dynamic Layouts
Layouts can also be used dynamically. We might only want the admin layout to be used when a user is logged in. This can be done by passing a symbol as the argument to the layout command and creating a method with the same name as the symbol which determines which layout should be used.
class ProjectsController < ApplicationController
layout :user_layout
def index
@projects = Project.find(:all)
end
protected
def user_layout
if current_user.admin?
"admin"
else
"application"
end
end
end
We can even restrict a layout to a single action in a controller with the render command.
def index @projects = Project.find(:all) render :layout => 'projects' end
The layout specified with the render command will override any controller-specific layout. To render an action with no layout we can use
render :layout => false
Notes
- In Rails 2 and above the file should be called
application.html.erb - Again, for Rails 2 and above the extension should be
.html.erbrather than.rhtml.



