Skip to content

Ruby on Rails Views Deep — Advanced ERB and Template Patterns

DodaTech Updated 2026-06-28 4 min read

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

What is the difference between render and redirect_to?

render renders a template. redirect_to sends a 302 to another URL.

Can I use other template engines besides ERB?

Yes. Rails supports Haml, Slim, and others through gems.

How do I render JSON in a view?

Use render json: @product in the controller, not in a view file.

What is a decorator in Rails?

A decorator wraps a model with view-specific methods. Draper gem is popular.

Can I share partials across controllers?

Yes. Place shared partials in views/application/.

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