homeASCIIcasts

7: All About Layouts 

(view original Railscast)

Other translations: It Es Fr

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:

Basic page without layout

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.

Basic page with layout

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 %>
Basic page with controller-specific layout

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

  1. In Rails 2 and above the file should be called application.html.erb
  2. Again, for Rails 2 and above the extension should be .html.erb rather than .rhtml.