Form Helpers for Collection in One Form
A usage of form helpers for a single record is easy and straightforward. But how to use them for a collection of records in one form?
Do we need to edit a collection of records in one form? Well, there is always an option to let a user to edit records one by one, and we should use this option if the structure of a record is complex, e.g. a lot of items. If the structure is simple or we use a subset of a complex structure, we can allow a user to edit more records in one form. A good examples are labels of photos in a photo album, description and price for items in a web shop, etc.
If a form helper is used for a collection, it is necessary to add an index to its id. For example:
- the id of a form element for a single record
book[author] - the id of a form element for a collection of records
book[1][author]that is a book with the primary key 1 and its field
author.
Unfortunately, there is no united way how to add an index for all form helpers. In the following list I will show how a form helper is used for a single record and then how it is necessary to use it for a collection of records.
In the examples below I assume there is a Book model with fields such as label, published_on, note and one has_one author relationship to an Author model.
text_field
Single Record
Ruby
<%= text_field ‘book’, ‘label’ %>Collection of Records
It is very easy to set an index value for the helper. It is necessary to add the
:indexattribute to the (third)optionsparameter:Ruby
<%= text_field ‘book’, ‘label’, :index => @book.id %>
text_area
Single Record
Ruby
<%= text_area ‘book’, ‘note’ %>Collection of Records
Similarly as for the
text_fieldform helper, it is easy — just to add the:indexattribute.Ruby
<%= text_area ‘book’, ‘note’, :index => @book.id %>
select
Single Record
Ruby
<%= select ‘book’, ‘author_id’, @authors %>with a blank value:
Ruby
<%= select ‘book’, ‘author_id’, @authors, :include_blank => true %>Collection of Records
For the helper it is necessary to add the
:indexattribute, but it is tricky. The helper is defined as:Ruby
select(object, method, choices, options = {}, html_options = {})The
:indexattribute is accepted only in the (fourth)html_optionsparameter, so we have to explicitly say that by adding an empty or a non empty set as the (third)optionsparameter.Ruby
<%= select ‘book’, ‘author_id’, @authors, {}, :index => @book.id %>with a blank value:
Ruby
<%= select ‘book’, ‘author_id’, @authors, {:include_blank => true}, :index => @book.id %>
select_date, select_time and select_datetime
Single Record
Ruby
<%= select_date ‘book’, ‘published_on’ %>with a blank value:
Ruby
<%= select_date ‘book’, ‘published_on’, :include_blank => true %>Collection of Records
Well, the worst situation is with the
select_date,select_timeandselect_datetime helpers. Basically you have to use the particularselect_year,select_monthandselect_dayhelpers (for a time select alsoselect_hour,select_minuteandselect_secondhelpers).For each select helper two attributes have to be specified:
- the
:prefixattribute contains a value in theobject_name[index]format, e.g."book[#{@book.id}]“- the
:field_nameattribute specifies what will be written in the last square brackets. A value consists of two parts: field name and helper index in round brackets, e.g.'published_on(1i)'for the year select. The following table show all helper indices:
- 1i year
- 2i month
- 3i day
- 4i hour
- 5i minute
- 6i second
The following example contains at the beginning a definition of the
prefixvariable that a little simplifies already complicated notation:Ruby
<% prefix = "book[#{@book.id}]" %> <%= select_year @book.published_on, :prefix => prefix, :field_name => "published_on(1i)" %> - <%= select_month @book.published_on, :prefix => prefix, :field_name => "published_on(2i)" %> - <%= select_day @book.published_on, :prefix => prefix, :field_name => "published_on(3i)" %> <%= select_hour @book.published_on, :prefix => prefix, :field_name => "published_on(4i)" %> : <%= select_minute @book.published_on, :prefix => prefix, :field_name => "published_on(5i)" %> : <%= select_second @book.published_on, :prefix => prefix, :field_name => "published_on(6i)" %>with a blank value (a shortened example; of course, it is necessary to add the
:include_blankattribute to all select helpers):Ruby
<%= select_year @book.published_on, :prefix => prefix, :field_name => "published_on(1i)", :include_blank => true %>
Conclusion
It was shown how to use form helpers for a collection of records in one form. Definitely the date & time select helpers should support the :index attribute.
Thanks
… to Mark Reginald James form Australia for his response on the RoR mailinglist (about the date_select in a collection).










