📖 Scenario: You are building a simple blog page in a Rails app. You want to use a layout to keep the header and footer consistent across pages. You also want to add a custom title and a sidebar only on the blog page using content_for.
🎯 Goal: Create a Rails layout with a header and footer. Use content_for in the blog view to add a page title and a sidebar section. The layout should display these sections if they exist.
📋 What You'll Learn
Create a layout file app/views/layouts/application.html.erb with a header and footer
Use yield to render the main content
Use content_for blocks for :title and :sidebar in the layout
In the blog view app/views/blog/index.html.erb, set content_for :title with the text 'My Blog'
In the blog view, set content_for :sidebar with a list of links
Ensure the layout shows the title in the <title> tag and the sidebar in a <aside> element
💡 Why This Matters
🌍 Real World
Layouts and content_for are used in Rails apps to keep page structure consistent and allow pages to customize parts like titles and sidebars easily.
💼 Career
Understanding layouts and content_for is essential for Rails developers to build maintainable and DRY web applications.
Use HTML tags <header>, <main>, and <footer>. Inside <main>, add <%= yield %> to show the page content.
2
Add content_for blocks for title and sidebar in layout
In app/views/layouts/application.html.erb, add a <title> tag inside <head> that uses content_for?(:title) ? yield(:title) : 'Default Title'. Below the <main> section, add an <aside> that renders yield(:sidebar) only if content_for?(:sidebar) is true.
Ruby on Rails
Hint
Use content_for?(:title) and yield(:title) inside the <title> tag. Use a conditional if content_for?(:sidebar) to show the <aside> with yield(:sidebar).
3
Set content_for :title in blog index view
In app/views/blog/index.html.erb, add a content_for block for :title that sets the text 'My Blog'.
Ruby on Rails
Hint
Use <% content_for :title do %> and <% end %> to wrap the title text.
4
Set content_for :sidebar with links in blog index view
In app/views/blog/index.html.erb, add a content_for block for :sidebar that contains an unordered list <ul> with three list items <li> containing links: 'Home', 'About', and 'Contact'. Use link_to with '#' as href for each link.
Ruby on Rails
Hint
Wrap the links inside <ul> and <li> tags inside a content_for :sidebar do block.
Practice
(1/5)
1. What is the main purpose of using content_for in Rails layouts?
easy
A. To define the main layout file for the application
B. To insert specific content into named sections of a layout
C. To create a new controller action
D. To style the page with CSS
Solution
Step 1: Understand the role of layouts
Layouts provide a shared structure like headers and footers for pages.
Step 2: Understand content_for usage
content_for allows views to add content to specific named areas in the layout.
Final Answer:
To insert specific content into named sections of a layout -> Option B
Quick Check:
content_for inserts content into layout spots [OK]
2. Which of the following is the correct syntax to define a content block named :sidebar in a Rails view?
easy
A. <%= yield :sidebar %>
B. <% content_for :sidebar = 'Sidebar content' %>
C. <% sidebar_content 'Sidebar content' %>
D. <%= content_for :sidebar do %>Sidebar content<% end %>
Solution
Step 1: Recall content_for block syntax
The correct way is to use content_for :name do ... end with ERB tags.
Step 2: Check each option
<%= content_for :sidebar do %>Sidebar content<% end %> uses <%= content_for :sidebar do %> ... <% end %> which is correct syntax. <% content_for :sidebar = 'Sidebar content' %> tries assignment incorrectly. <%= yield :sidebar %> is for yielding, not defining. <% sidebar_content 'Sidebar content' %> is invalid.
Final Answer:
<%= content_for :sidebar do %>Sidebar content<% end %> -> Option D
Quick Check:
Use content_for :name do ... end to define content [OK]
Hint: Use content_for :name do ... end to define blocks [OK]
<%= content_for :header do %>Welcome Header<% end %>
Main content here
<%= content_for :footer do %>Footer Info<% end %>
What will be rendered inside the <main> tag?
medium
A. Footer Info
B. Welcome Header
C.
Main content here
D. Nothing
Solution
Step 1: Understand yield usage in layout
yield without arguments renders the main view content. yield :header and yield :footer render named content blocks.
Step 2: Identify main content in view
The main content is the part outside content_for blocks: <p>Main content here</p>.
Final Answer:
<p>Main content here</p> -> Option C
Quick Check:
Main content = yield without args = <p>Main content here</p> [OK]
Hint: Main content is outside content_for, shown by plain yield [OK]
Common Mistakes:
Thinking content_for blocks appear in main yield
Confusing named yields with main yield
Ignoring content outside content_for
4. You have this layout snippet:
<header><%= yield :title %></header>
And this view code:
<% content_for :title = 'Page Title' %>
Why does the title not appear in the header when rendering?
medium
A. Because content_for must use a block, not assignment
B. Because yield is missing in the layout
C. Because the layout file is not linked properly
D. Because content_for only works in controllers
Solution
Step 1: Check content_for syntax in view
The code uses assignment content_for :title = 'Page Title', which is invalid syntax.
Step 2: Correct usage of content_for
content_for requires a block: content_for :title do 'Page Title' end or content_for(:title) { 'Page Title' }.
Final Answer:
Because content_for must use a block, not assignment -> Option A
Quick Check:
content_for needs blocks, not assignment [OK]
Hint: Always use blocks with content_for, not assignment [OK]
Common Mistakes:
Using assignment instead of block for content_for
Forgetting to yield named content in layout
Assuming content_for works in controllers
5. You want to create a layout that shows a custom page title if provided, or a default title otherwise. Which layout code correctly uses content_for and yield to achieve this?
hard
A. <title><%= content_for?(:title) ? yield(:title) : 'Default Title' %></title>
B. <title><%= yield(:title) || 'Default Title' %></title>
C. <title><%= content_for(:title) || 'Default Title' %></title>
D. <title><%= yield :title if content_for?(:title) %></title>
Solution
Step 1: Understand content_for? and yield
content_for?(:title) checks if content was provided. yield(:title) outputs it.
Step 2: Check each option for fallback logic
<title><%= content_for?(:title) ? yield(:title) : 'Default Title' %></title> uses a ternary to show yield(:title) if present, else 'Default Title'. <title><%= yield(:title) || 'Default Title' %></title> uses yield(:title) || 'Default Title' but yield(:title) returns nil if no content, so fallback works but less explicit. <title><%= content_for(:title) || 'Default Title' %></title> uses content_for(:title) which returns nil and does not output content. <title><%= yield :title if content_for?(:title) %></title> only yields if content exists but shows nothing otherwise.