---
title: Rendering Collections in Rails
teaser:
tags: web,rails
author: Joël Quenneville
published_on: 2013-12-31
---

Partials are a great way to break down complex view into more manageable chunks
as well as keeping view code DRY. However, rendering a partial for each item in
a collection looks ugly:

    <% @user.comments.each do |comment| %>
      <%= render partial: 'comments/comment', locals: { comment: comment } %>
    <% end %>

## Partial paths

Luckily, Rails gives us this beautiful shorthand syntax:

    render @user.comments

How does this magic work? Under the hood, `render` calls `to_partial_path` on
each of our objects to determine which partial to render. Models that inherit
from `ActiveRecord::Base` will return a partial name based on the model's name
by default. For example:

    User.new.to_partial_path
    # => 'users/user'

You can override this:

    class User < ActiveRecord::Base
      def to_partial_path
        'users/profile'
      end
    end

## POROs

This works with plain old Ruby objects too. Here's a [Null Object
Pattern][null] example:

    class Guest
      def name
        'Guest'
      end

      def to_partial_path
        'users/user'
      end
    end

`@dashboard.users_online` is a mix of ActiveRecord User objects and
non-persisted Guest objects:

      <h1>Users online:</h1>
      <%= render @dashboard.users_online %>

The same partial is used for both guests and registered users:

      <%= user.name %>

## Heterogeneous collections

It gets even better. The objects in the collection can be of different types,
each with their own partial.

`@user.favorites` can contain any combination of Article, Comment, and Image
objects:

    <h1><%= @user.name %>'s Favorites</h1>
    <%= render @user.favorites %>

*app/views/articles/_article.html.erb*:

    <h1><%= article.name %></h1>
    <p><%= article.content %></p>

*app/views/comments/_comment.html.erb*:

      <div class="comment">
       <em>Last updated: <%= comment.updated_at %></em>
       <p><%= comment.content %></p>
      </div>

*app/views/images/_image.html.rb*:

      <h1><%= image.title %></h1>
      <%= image_tag image.url %>

The beauty of this polymorphic approach is that we don't have to write any
conditional code. As long as all the objects in the collection define
`to_partial_path`, it all just works.

## What's next

If you found this useful, you might also enjoy:

* [Ruby Science][science] to read more about replacing conditionals with
  polymorphism in Ruby
* [Using Polymorphism to Make a Better Activity Feed in Rails][activity] to see
  another example of polymorphic Rails partials

[null]: https://thoughtbot.com/blog/rails-refactoring-example-introduce-null-object
[science]: http://rubyscience.com
[activity]: https://thoughtbot.com/blog/using-polymorphism-to-make-a-better-activity-feed-in-rails
