nathanvda/cocoon — pull request #86 by porecreat (2012-09-14 17:20:25+00:00)
Title: Handle Array fields

Here's my proposal to fix #85.

I've added 3 methods :

- `link_to_remove_array_element`
- `render_array_element`
- `link_to_add_array_element`

Those are mostly copy/paste from `link_to_remove_association`, `render_association` and `link_to_add_association`, except they don't require an object association.

By doing this, we loose some sugar from rails, simple_form and formtastic since we don't use `*fields_for` anymore but it allows a cleaner DB design when you need a single sub-field association.

I've found only one way to handle this case (it's haml + bootstrap).

Here's the main form where I must use `@model.array_field.each do |array_field_element|` instead of `*fields_for ...` (do not care about example model & field names, I just took them from my working case) :

````haml
[...]
%table{id: paths}
%thead
%tr
%th= link_to_add_array_element '', f, :paths, { class: 'icon-plus', data: {:'association-insertion-traversal' => :closest, :'association-insertion-node' => 'table#paths', :'association-insertion-method' => :append } }
%th Paths
%tbody.nested-fields
- @service.paths = [''] if @service.paths.blank? # We could also set this as a default value in the model
- @service.paths.each do |path|
= render partial: 'path_field', locals: { f: f, value: path }
[...]
````

And here is my `_path_field` partial (note `_field` is singular since there can be only one field) :

````haml
%tr.nested-fields
%td= link_to_remove_array_element '', f, { class: 'icon-trash' }
= f.input :paths, wrapper: :td, input_html: { name: "#{f.object_name}[paths][]", value: value }
````

As you can see, `name` and `value` field attributes have to be manually set since they're not provided by an associated object.

I my patch, value is provided by cocoon when adding new fields (empty string). Default value of a new array element can't be set in the model (we can only set a full default array), but we could make cocoon handle this (not very MVCful but...it's just a default value...).

The only original method I've changed is `get_partial_path`, to use `_field` suffix instead of `_fields` for the partial name when `link_to_add_array_element` is called. The original behavior has not been changed at all except this point.

I did not update specs and readme yet since it's only a proposal for now, which probably needs a little more polish. I'll update them if you're willing to merge.