Mildly Internet
February 13, 2014 | code

Collections and to_partial_path

Rendering collections of Active Record models is really quite clean. Calling:

<%= render @article.posts %>

Effectively calls:

<%= render partial: "posts/post", locals: { post: post } %>

Internally, the render method calls to_partial_path on each item of the collection to figure out which partial to render (in this case, posts/post). ActiveRecord models inherit a method which returns a partial name based on the name of the model. However, it is possible to overwrite said behavior. Plain Ruby objects are able to implement the same behaviour.

class Article < ActiveRecord::Base
  def to_partial_path
    "articles/summary"
  end
end

class Spaceship
  def name
    "Serenity"
  end

  def to_partial_path
    "transports/firefly"
  end
end

class Train
  def to_partial_path
    "transports/train"
  end
end

# In the view
<%= render @transports %>

Lets use this fact to render out an event feed. Each event has a type column (comment, star, upload, etc.). Each event in the feed is displayed differently, and has a corresponding partial in the events folder. Instead of doing a switch on type in the view or model, we can take advantage of to_partial_path to dynamically figure out the correct partial to render.

class Event < ActiveRecord::Base
  def to_partial_path
    "events/#{type}"
  end
end

....
<%= render @events %>