Skip to content

Rails Partials and Collections — Reusable View Rendering

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Rails Partials and Collections. We cover key concepts, practical examples, and best practices to help you master this topic.

Rails partial collections render an array of objects using a shared partial template, supporting collection Caching, spacer templates, and automatic counter variables.

What You'll Learn

By the end of this tutorial, you'll render partial collections, use collection caching, implement spacer templates, group collection items, and optimize collection rendering.

Why Collections Matter

Rendering collections with partials is more efficient than manual iteration. Collection caching with :cached option dramatically reduces rendering time for repeated views.

Real-World Use

A product listing page renders @products collection with cached partials. The first request renders 50 products, but subsequent requests serve cached fragments without re-rendering.

Collections Path

flowchart LR
  A[Rails Views] --> B[Partials Collections]
  B --> C[Render Collection]
  B --> D[Collection Caching]
  B --> E[Spacer Templates]
  B --> F[Grouping]
  B --> G{You Are Here}
  style G fill:#f90,color:#fff

Basic Collection Rendering

Render a collection with a partial.

<%# views/products/index.html.erb %>
<h1>Products</h1>

<!-- Full syntax -->
<%= render partial: "product", collection: @products %>

<!-- Shorthand (infers partial name from model) -->
<%= render @products %>

<!-- With locals -->
<%= render partial: "product", collection: @products, locals: { show_price: true } %>

<!-- With a different variable name -->
<%= render partial: "product", collection: @products, as: :item %>

Counter and Iteration Variables

Access collection metadata in partials.

<%# views/products/_product.html.erb %>
<tr class="<%= product_counter.even? ? "even" : "odd" %>">
  <td><%= product_counter + 1 %></td>
  <td><%= product.name %></td>
  <td><%= number_to_currency(product.price) %></td>
  <td>
    <% if product_iteration.first? %>
      <span class="badge bg-primary">New</span>
    <% end %>
    <% if product_iteration.last? %>
      <span class="badge bg-info">Last</span>
    <% end %>
  </td>
</tr>

Collection Caching

Cache each partial fragment individually.

<%# views/products/index.html.erb %>
<h1>Products</h1>

<!-- Cache each product partial -->
<%= render partial: "product", collection: @products, cached: true %>

<!-- Or with the shorthand -->
<%= render @products, cached: true %>
<%# views/products/_product.html.erb %>
<% cache product do %>
  <div class="product-card">
    <%= image_tag product.thumbnail if product.thumbnail.attached? %>
    <h3><%= link_to product.name, product %></h3>
    <p><%= number_to_currency(product.price) %></p>
    <%= render "reviews/summary", product: product %>
  </div>
<% end %>

Spacer Templates

Add separators between rendered items.

<%# views/products/index.html.erb %>
<%= render partial: "product", collection: @products, spacer_template: "product_separator" %>
<%# views/products/_product_separator.html.erb %>
<hr class="product-divider">

Empty Collections

Handle empty collections gracefully.

<%# views/products/index.html.erb %>
<%= render @products, cached: true %>
<% if @products.empty? %>
  <div class="empty-state">
    <h2>No products yet</h2>
    <p>Be the first to add a product!</p>
    <%= link_to "Add Product", new_product_path, class: "btn btn-primary" %>
  </div>
<% end %>

Common Mistakes

1. Forgetting Cached: True for Large Collections

Rendering 100+ items without caching creates slow pages. Always use cached: true.

2. Overriding As Without Updating Counter Variable

Render with as: :item changes the counter to item_counter. Update references accordingly.

3. Using Each Instead of Render Collection

Manual iteration with each cannot use collection caching.

4. Missing Cache Keys

cached: true requires each partial to have a cache block around its content.

5. Not Handling Empty Collections

Render returns empty string for empty collections. Explicit empty state is better UX.

Practice Questions

1. How do you render a collection with cached partials?

<%= render partial: "product", collection: @products, cached: true %>

2. What are counter variables in collection partials?

model_counter (0-indexed position) and model_iteration (with first?, last?, etc.).

3. What is a spacer template?

A partial rendered between each element in a collection.

4. How does cached: true speed up rendering?

It caches each partial fragment individually by its cache key. Cached items skip rendering.

5. Challenge: Render a cached product grid with spacer.

<%= render partial: "product_card", collection: @products, cached: true, spacer_template: "grid_gap" %>
<% if @products.empty? %>
  <p>No products available.</p>
<% end %>

FAQ

What happens if I use cached: true without cache blocks?

The partial renders normally without caching. cached: true requires cache blocks.

Can I use cached: true with the shorthand render?

Yes. <%= render @products, cached: true %> works.

What is the default variable name in a collection partial?

The singularized model name (product for Product).

How do I pass different locals per item?

Use map to transform the collection or pass locals to the render call.

Can I use cached: true with non-ActiveRecord collections?

Yes. Use cache key: key_proc option or manual cache blocks.

Mini Project: Cached Product Grid

Build a product grid with collection caching.

<%# products/index.html.erb %>
<div class="product-grid">
  <%= render partial: "product_tile", collection: @products, cached: true %>
</div>
<%# products/_product_tile.html.erb %>
<% cache product_tile do %>
  <div class="tile">
    <%= link_to product_path(product_tile) do %>
      <%= image_tag product_tile.thumbnail if product_tile.thumbnail.attached? %>
      <h4><%= product_tile.name %></h4>
      <p><%= number_to_currency(product_tile.price) %></p>
    <% end %>
  </div>
<% end %>

What's Next

Rails Models Deep Rails ActiveRecord Deep Rails Views Deep

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro