My Octopress Blog

A blogging framework for hackers.

Handling Multiple Object Types With the Same Partial

I’m currently using a single form partial to handle multiple objects that are all using STI. This usually isn’t a problem because the form_for helper lets you keep the actual object anonymous, like this:

<p><b>Name</b><br /><%= region_form.text_field :name %></p>

But what happens when you want to use a helper that doesn’t work so well with the

region_form.text_field
objects?

I did a little bit of digging into the default object that is passed into the partial, and this is what I found:

region_form.object_name

This lets me implement my multiple select for every type of object, without having to specify anything explicitly.

Example:

In the view:

<% form_for(:province, :url => provinces_path) do |f| %>
 <%= render :partial => 'shared/region_form', :object => f %>
 <p><%= submit_tag "Create" %> or <%= link_to 'Cancel', provinces_path %></p>
<% end %>

In the helper shared/_region_form.html:

<p><b>Name</b><br /><%= region_form.text_field :name %></p>
<p><label for="alias_region_id">Aliased By:</label><br />
<%= select_tag(
               "#{region_form.object_name}[aliased_by][]",
               options_from_collection_for_select(
                 Region.find(:all),
                 'id',
                 'title',
                 instance_variable_get("@#{region_form.object_name}").aliased_by_ids),
               :multiple => true
             )
%></p>

So, we use a combination of region_form.object name and instance_variable_get to make the form handle whatever object we throw at it.

Yay ruby!