Rails Layouts and Partials — Reusable View Components
In this tutorial, you will learn about Rails Layouts and Partials. We cover key concepts, practical examples, and best practices to help you master this topic.
Rails layouts and partials enable reusable view components with layout inheritance, nested layouts, shared partials across controllers, and content_for blocks for dynamic content.
What You'll Learn
By the end of this tutorial, you'll create application layouts with nested content, use content_for blocks, render partials with locals, create shared partials, and organize template inheritance.
Why Layouts and Partials Matter
Layouts provide consistent page structure. Partials eliminate duplicated HTML. Together they keep views DRY and maintainable.
Real-World Use
An admin panel uses a different layout than the public site. Both layouts include shared partials for navigation and footer. Each layout yields content_for blocks for page-specific scripts.
Layouts Path
flowchart LR
A[Rails Views] --> B[Layouts Partials]
B --> C[Layout Inheritance]
B --> D[Content For]
B --> E[Shared Partials]
B --> F[Nested Layouts]
B --> G{You Are Here}
style G fill:#f90,color:#fff
Application Layout
The default layout for all views.
<%# views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
<title><%= content_for?(:title) ? yield(:title) : "My App" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<body>
<%= render "layouts/navigation" %>
<main class="container">
<%= render "layouts/flash_messages" %>
<%= yield %>
</main>
<%= render "layouts/footer" %>
</body>
</html>
Nested Layouts
Use different layouts per controller.
# app/controllers/admin_controller.rb
class AdminController < ApplicationController
layout "admin"
end
<%# views/layouts/admin.html.erb %>
<% content_for :head do %>
<%= stylesheet_link_tag "admin" %>
<% end %>
<div class="admin-layout">
<aside><%= render "admin/sidebar" %></aside>
<main><%= yield %></main>
</div>
<%= render template: "layouts/application" %>
Partials with Locals
Pass variables to partials.
<%# views/products/show.html.erb %>
<%= render "product_card", product: @product, show_details: true %>
<%# views/products/index.html.erb %>
<%= render partial: "product_card", collection: @products, as: :product, locals: { show_details: false } %>
<%# views/products/_product_card.html.erb %>
<div class="product-card">
<h3><%= link_to product.name, product %></h3>
<p><%= number_to_currency(product.price) %></p>
<% if local_assigns[:show_details] %>
<p><%= product.description %></p>
<%= link_to "Edit", edit_product_path(product) %>
<% end %>
</div>
Counter and Iteration
Built-in counter variables in partial collections.
<%# views/products/index.html.erb %>
<%= render partial: "product_row", collection: @products %>
<%# views/products/_product_row.html.erb %>
<tr class="<%= product_row_counter.even? ? "even" : "odd" %>">
<td><%= product_row_counter + 1 %></td>
<td><%= product_row.name %></td>
<td><%= number_to_currency(product_row.price) %></td>
<td>
<% if product_row_iteration.first? %>
<span class="badge">New</span>
<% end %>
<% if product_row_iteration.last? %>
<span class="badge">Last</span>
<% end %>
</td>
</tr>
Common Mistakes
1. Hardcoding Layout Names in Actions
Use layout :name in the controller instead of render layout: "name" in each action.
2. Not Using Content For for Page-Specific Assets
Adding scripts and styles inline instead of content_for blocks clutters the head.
3. Over-Nesting Partials
Partials calling partials calling partials becomes unmanageable. Limit nesting to 2-3 levels.
4. Using @ Variables in Partials
Partials should receive locals, not depend on controller instance variables.
5. Not Using Render Collection for Lists
Manually iterating with each in a partial is slower than render collection.
Practice Questions
1. How do you specify a different layout for a controller?
Use layout "admin" in the controller class definition.
2. What is a nested layout?
A layout that wraps another layout. The inner layout yields to the outer layout.
3. How do you pass local variables to a partial?
Use locals: { key: value } in the render call.
4. What are counter variables in partials?
product_row_counter and product_row_iteration provide index and iteration metadata.
5. Challenge: Create an admin layout with sidebar and nested content.
<%# views/layouts/admin.html.erb %>
<% content_for :head, stylesheet_link_tag("admin") %>
<div class="admin-wrapper">
<nav><%= render "admin/sidebar" %></nav>
<main><%= yield %></main>
</div>
<%= render template: "layouts/application" %>
FAQ
Mini Project: Two-Layout Application
Build an application with public and admin layouts.
class ApplicationController < ActionController::Base
layout :layout_by_resource
private
def layout_by_resource
if devise_controller? && resource_name == :admin
"admin"
else
"application"
end
end
end
What's Next
Rails Helpers Rails Partials Collections Rails Views Deep
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro