I have a STI table and want to be able to render a collection using

render @collection 

with every elements of the collection using their own partial or, if they don't have one, the parent partial. You know, partial inheritance.

So I added to my parent model :

def to_partial_path


# a little hack to get partial inheritance in views, check if the partial exist, if not
# return the parent's one. Provide class level cache, be sure to restart your app when
# adding/removing partials.
def self._to_partial_path
  @_to_partial_path ||= begin
    element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self))
    collection = ActiveSupport::Inflector.tableize(self)
    if File.exists?(Rails.root.join('app', 'views', collection, "_#{element}.html.erb")) ||
    self.superclass == ActiveRecord::Base


The original code is here.

This seems to work great so far but I want to have some opinions.

Should I have gone another way?

Are there any "gotchas" I might encounter doing it this way?

Any way to refactor this?

edit: No problem whatsoever, it's working great for now. I'm looking for a way to achieve something similar with form (ie render form in new and edit views render the child _form partial if their is one, the parent one otherwise).


1 Answer 1


This actually looks pretty solid.

Another approach would be to sub-class the Renderer and make it responsible for retrieving the base classes' to_partial_path.

For me this feels a bit cleaner because it is sub-classing versus monkey-patching and because the renderer is supposed to find and load the template anyway while the model class shouldn't case about the (non-)existence of the view at all.

After looking at it for a while, I would the make sub-classes partial_path check if the template exists and find the template of the base class if it doesn't.

  • 1
    \$\begingroup\$ How would you let Rails know that it should use the PartialRenderer subclass? Is their a hook for that (I haven't found one)? \$\endgroup\$ May 7, 2014 at 22:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.