patternrubyrailsMinor
Rails partial inheritance hack
Viewed 0 times
inheritancerailshackpartial
Problem
I have a STI table and want to be able to render a collection using
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 :
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
render @collectionwith 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
endThe 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'
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.
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.