Ruby on Rails Views Deep — Advanced ERB and Template Patterns
In this tutorial, you will learn about Ruby on Rails Views Deep. We cover key concepts, practical examples, and best practices to help you master this topic.
Rails views render templates with ERB, partials, helpers, layouts, and content_for blocks, supporting collection rendering, fragment Caching, and view components.
What You'll Learn
By the end of this tutorial, you'll render ERB templates, use content_for and yield, create view helpers, render partial collections, cache view fragments, and use view components.
Why Views Matter
Views generate the HTML that users interact with. Well-organized views with partials and helpers remain maintainable as the UI grows.
Real-World Use
A blog uses partials for post rendering with collection caching, helpers for formatting dates and times, and content_for for per-page title and meta tags.
Views Path
flowchart LR
A[Rails MVC] --> B[Views Deep]
B --> C[ERB]
B --> D[Partials]
B --> E[Helpers]
B --> F[Caching]
B --> G{You Are Here}
style G fill:#f90,color:#fff
ERB Template Syntax
Embed Ruby in HTML templates.
<%# products/index.html.erb %>
<h1><%= @category.name %></h1>
<% if @products.any? %>
<ul>
<% @products.each do |product| %>
<li>
<%= link_to product.name, product %>
<span class="price"><%= number_to_currency(product.price) %></span>
</li>
<% end %>
</ul>
<% else %>
<p>No products found.</p>
<% end %>
Content For and Yield
Define content blocks for layouts.
<%# views/products/show.html.erb %>
<% content_for :title, @product.name %>
<% content_for :meta_description, truncate(@product.description, length: 160) %>
<% content_for :sidebar do %>
<%= render "products/sidebar", product: @product %>
<% end %>
<h1><%= @product.name %></h1>
<p><%= @product.description %></p>
<%# views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
<title><%= content_for?(:title) ? yield(:title) : "Default Title" %></title>
<meta name="description" content="<%= yield(:meta_description) %>">
</head>
<body>
<aside><%= yield :sidebar %></aside>
<main><%= yield %></main>
</body>
</html>
Partial Collections
Render collections with partials.
<%# views/products/index.html.erb %>
<h1>Products</h1>
<%= render partial: "product", collection: @products, as: :product, locals: { show_price: true } %>
<!-- With shorthand -->
<%= render @products %>
<%# views/products/_product.html.erb %>
<div class="product" id="<%= dom_id(product) %>">
<h3><%= link_to product.name, product %></h3>
<% if local_assigns[:show_price] %>
<p><%= number_to_currency(product.price) %></p>
<% end %>
<p><%= truncate(product.description, length: 100) %></p>
</div>
View Helpers
Custom helpers for view logic.
# app/helpers/products_helper.rb
module ProductsHelper
def product_status_badge(product)
if product.published?
content_tag :span, "Published", class: "badge badge-success"
elsif product.draft?
content_tag :span, "Draft", class: "badge badge-warning"
else
content_tag :span, "Archived", class: "badge badge-secondary"
end
end
def format_price(amount, currency = "USD")
number_to_currency(amount, unit: currency == "USD" ? "$" : "€")
end
def product_thumbnail(product, size: :small)
if product.image.attached?
image_tag product.image.variant(resize_to_limit: size == :small ? [100, 100] : [300, 300])
else
image_tag "placeholder.png"
end
end
end
Fragment Caching
Cache expensive view fragments.
<%# views/products/index.html.erb %>
<h1>Products</h1>
<% cache @products do %>
<%= render @products %>
<% end %>
<%# views/products/_product.html.erb %>
<% cache product do %>
<div class="product">
<h3><%= link_to product.name, product %></h3>
<p><%= number_to_currency(product.price) %></p>
<%= render "reviews_summary", product: product %>
</div>
<% end %>
Common Mistakes
1. Logic-Heavy Views
Views should display data, not compute it. Use helpers or decorators for presentation logic.
2. Not Using Partials for Repeated HTML
Duplicating HTML across views violates DRY. Extract repeated sections to partials.
3. Missing Content For Defaults
yield(:title) returns empty string if not set. Check content_for?(:title) first.
4. Overusing Instance Variables
Pass locals to partials instead of relying on @variables from controllers.
5. Caching Without Cache Keys
Without proper cache keys, cached content becomes stale. Use model instances as cache keys.
Practice Questions
1. What is the difference between render @products and render partial: product, collection: @products?
They are equivalent. render @products infers the partial name from the model class.
2. How do you pass local variables to a partial?
Use render partial: "form", locals: { product: @product }.
3. What does content_for do?
Stores content blocks that can be yielded in layouts or other templates.
4. How do you cache a view fragment?
Wrap the fragment in a cache block: <% cache product do %> ... <% end %>.
5. Challenge: Create a view with partials, caching, and content_for.
<% content_for :title, "Product: #{@product.name}" %>
<% cache @product do %>
<h1><%= @product.name %></h1>
<%= render "product_details", product: @product %>
<%= render @product.reviews.published %>
<% end %>
FAQ
Mini Project: Product Listing with Caching
Build a cached product listing view.
<% cache("products_index-page_#{params[:page]}", expires_in: 1.hour) do %>
<div class="products-grid">
<%= render partial: "product_card", collection: @products, cached: true %>
</div>
<%= paginate @products %>
<% end %>
<%# _product_card.html.erb %>
<% cache(product_card) do %>
<div class="card">
<%= image_tag product_card.image.variant(:thumb) if product_card.image.attached? %>
<h3><%= link_to product_card.name, product_card %></h3>
<p><%= number_to_currency(product_card.price) %></p>
</div>
<% end %>
What's Next
Rails Layouts Partials Rails Helpers Rails Partials Collections
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro