Performance: Layouts and content_for
This affects the server-side rendering speed and the size of the HTML sent to the browser, impacting initial page load time.
<!-- layout.html.erb -->
<html>
<head>
<title>My Site</title>
</head>
<body>
<%= yield %>
<%= yield :sidebar %>
</body>
</html>
<!-- page.html.erb -->
<h1>Welcome</h1>
<div>Content here</div>
<% content_for :sidebar do %>
<div>Sidebar content</div>
<% end %><!-- layout.html.erb -->
<html>
<head>
<title>My Site</title>
</head>
<body>
<%= yield %>
<%= yield :sidebar %>
</body>
</html>
<!-- page.html.erb -->
<h1>Welcome</h1>
<div>Content here</div>
<div>Sidebar content</div>| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| Using content_for to inject sidebar content | Minimal extra DOM nodes | No additional reflows | No extra paint cost | [OK] Good |
| Duplicating sidebar content in page templates | More DOM nodes due to duplication | Potential reflows if layout changes | Higher paint cost due to larger HTML | [X] Bad |
content_for in Rails layouts?content_for usagecontent_for allows views to add content to specific named areas in the layout.content_for inserts content into layout spots [OK]content_for fills layout placeholders [OK]content_for with layout definition:sidebar in a Rails view?content_for block syntaxcontent_for :name do ... end with ERB tags.<%= 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.content_for :name do ... end to define content [OK]content_for :name do ... end to define blocks [OK]content_foryield with content_for<html> <body> <header><%= yield :header %></header> <main><%= yield %></main> <footer><%= yield :footer %></footer> </body> </html>
<%= content_for :header do %>Welcome Header<% end %>Main content here
<%= content_for :footer do %>Footer Info<% end %>
<main> tag?yield usage in layoutyield without arguments renders the main view content. yield :header and yield :footer render named content blocks.content_for blocks: <p>Main content here</p>.<header><%= yield :title %></header>
<% content_for :title = 'Page Title' %>
content_for syntax in viewcontent_for :title = 'Page Title', which is invalid syntax.content_forcontent_for requires a block: content_for :title do 'Page Title' end or content_for(:title) { 'Page Title' }.content_for must use a block, not assignment -> Option Acontent_for needs blocks, not assignment [OK]content_for, not assignment [OK]content_forcontent_for works in controllerscontent_for and yield to achieve this?content_for? and yieldcontent_for?(:title) checks if content was provided. yield(:title) outputs it.<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.content_for? to check, then yield or fallback [OK]content_for?(:name) to check before yielding [OK]content_for instead of content_for? for checkingyield(:name) returns empty string instead of nilPass the test and this pattern moves unknown