The one area I keep hitting my head against in Rails is repeating fields via
javascript. I frequently have forms where one or more fields are actually
broken out into sub tables because there can be multiple simultaneous values.
Rails seems to want to you to use the [] construct in the form helpers (e.g.
text_field(''employee[]'', ''name'')), but I
can''t come up with an elegent way to
get that to work nicely where I want to let the user to add more entries with
fields that get added with javascript when the user clicks on a link.
I can definitely do it, but it gets kinda messy and I want to use partials
for the repeating fields, but I can''t figure out how to do it in a DRY
way.
Anyone got any ideas?
Here''s a concrete example:
Say you have a couple of database tables like this:
employees:
id
name
date_of_hire
employee_phone_numbers:
id
employee_id
phone_number
Now, say I want a page for editing an employee. Here''s a template:
edit.rhtml
<% form_for :employee, @employee, :url => {:action => ''update}
do |f| %>
<%= f.text_field name %>
<%= f.date_of_hire %>
<input type="sumbit" value="save"/>
<% end %>
This all works very neatly in Rails. The problem comes when I want to do some
javascript to let the user add one or more phone numbers to this employee on
the same page:
edit.rhtml
<% form_for :employee, @employee, :url => {:action => ''update}
do |f| %>
<%= f.text_field :name %>
<%= f.text_field :date_of_hire %>
<div id="phone_numbers">
<% for @employee_phone_number in @employee.employee_phone_numbers %>
<%= render :partial => ''phone_number'' %>
<% end %>
</div>
<%= link_to_function ''add phone number'', update_page {
|page| page.insert_html(:after, :phone_numbers, render :partial =>
''phone_number'')} %>
<input type="sumbit" value="save"/>
<% end %>
_phone_number.html
<% fields_for :employee_phone_number, @employee_phone_number do |f| %>
<%= f.text_field phone_number %>
<% end %>
This is where the rails model breaks down. Now that I have two
employee_phone_numbers on the page, if I hit save, they have the same name
(and id), so only one of them is passed in params to the update action.
So, I change my _phone_number.rhtml partial to:
<% fields_for ''employee_phone_number[]'',
@employee_phone_number do |f| %>
<%= f.text_field phone_number %>
<% end %>
and the ''add phone number'' link to:
<%= link_to_function ''add phone number'', update_page {
|page| @employee_phone_number = EmployeePhoneNumber.new;
page.insert_html(:after, :phone_numbers, render :partial =>
''phone_number'')} %>
This is a little closer, as now as long as the user only adds one phone
number (there was already an existing one with id 2), you get a params like
this:
{"employee_phone_number"=>{"phone_number"=>"510-555-5555",
"2"=>{"phone_number"=>"510-555-5555"}}
But if the user adds some more phone numbers, you only ever get the already
existing ones plus one of the new ones, just exactly the same as the above
params.
I can fix this by basically using a different partial for the ''add
phone
number'' link but that seems not very DRY to me. Anyone have an elegent
way of
doing this?