Rails is very helpful when it comes to automatically rendering a partial for a given object.

<% @startups.each do |startup| %>
 <%= render startup %> <!-- Renders startups/startup partial -->
<% end %>

This loop renders the startups/startup partial for every startup in the collection. If you want to change the partial it renders, you can override the #to_partial_path method on your object like this.

class Startup < ActiveRecord::Base
  def to_partial_path
   'startups/summary'
  end
end

This is great if you want change the partial path for all startup objects in your application. How about if you want to change the partial path only in a specific view?

Overriding #to_partial_path with a decorator

One approach is to use the decorator pattern wrap the model and override only the #to_partial_path method.

class StartupTile < SimpleDelegator
 def to_partial_path
 'startups/tile'
 end
end

StartupTile.new(Startup.new).to_partial_path #=> "startups/tile"

However, it can be very inconvenient to create a new class every time you want to customize an object’s partial path.

There’s a gem for that

We decided to generalize this solution and turn it into the partial_path_customizer gem. This gem includes a single method in your view helpers called #customize_partial_path.

<!-- Renders the "startups/tile" partial -->
<%= render customize_partial_path(startup, 'tile') %>

This code decorates the startup object and overrides #to_partial_path so it returns startups/tile. This also gets useful when you have a collection of multiple types of objects, possibly from a polymorphic relationship.

# Somewhere in the controller
@employees = [Developer.new, Designer.new, Developer.new]

# Then in the view
<%= render customize\_partial\_path(@employees, 'summary') %>

This renders the developers/summary, designers/summary, developers/summary partials, respectively.

The partial_path_customizer gem solves the problem of wanting to use Rails implicit rendering, but only being able to use it for one partial per object. Since this gem only wraps the object being rendered, you can still pass all of normal options to the #render that allow you to do things like caching partials.

<%= render customize\_partial\_path(@developers, 'summary'), cache: true %>

If you’d like to learn more about the basics of #to_partial_path, check out this blog article: http://robots.thoughtbot.com/rendering-collections-in-rails.

Please send us feedback on Twitter and let us know what you think.

Originally published at blog.animascodelabs.com on October 9, 2014.