May 24, 2006
Polymorphic partials
Versions of Ruby on Rails greater than 1.1 have support for polymorphic associations. This is an extremely handy feature, which allows objects of arbitrary types to be associated with each other. There are a few things about them that can get a bit thorny. One of these has to do with displaying associated items.
Normally, if one wanted to list all objects associated with a parent object, one would just create a partial template to display a list of the objects. A typical one might look like this…
-
# _object.rhtml
-
<li><%= object.name %></li>
The problem with this is that you need to know what kind of object you are going to render before you render it, which makes it difficult to list polymorphic data in a single list. So what do we do? We write a helper.
In this case, it’s pretty short. All it does is figure out what kind of object is being rendered and then looks up a partial template with a name identical to the model.
It looks like this…
-
# belongs in helpers/application_helper.rb
-
# finds the correct partial to use for a
-
# particular object type (for polymorphic lists)
-
def to_partial(object)
-
model_file = object.class.to_s.underscore
-
render :partial => "#{model_file}/#{model_file}", :object => object
-
end
This assumes that your controllers are named after the singular version of the model file. If they are the plural version, you probably want to do something like this..
-
# Use if controllers are plural form of model names
-
def to_partial(object)
-
model_file = object.class.to_s.underscore
-
controller_file = model_file.pluralize
-
render :partial => "#{controller_file}/#{model_file}", :object=>object
-
end
This code does not let you pass in any other options, or let you render a collection of objects.
For that you can use this…
-
def to_collection(collection)
-
collection.map {|object| to_partial(object)}
-
end
Filed by Kevin Olbrich at 9:07 am under Ruby on Rails
2 Comments
How about the form and the partial(s) for the form? What does that code look like? How can you know what instance to create or what partial to load?
This actually works fine with forms. You may want to modify the helper to accept an optional suffix so you can have multiple kinds of partials (say one for rendering and one for editing).