HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyrailsMinor

Rails partial inheritance hack

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
inheritancerailshackpartial

Problem

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
  self.class._to_partial_path
end

protected

# 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

      "#{collection}/#{element}"
    else
      self.superclass._to_partial_path
    end
  end
end


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).

Solution

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.

Context

StackExchange Code Review Q#16415, answer score: 3

Revisions (0)

No revisions yet.