Qui a dit que je faisait encore un billet avec un titre trop « complexe » ?

Il peut arriver que vous ayez besoin, dans un même formulaire, d’ajouter plusieurs uplets en même temps.
L’exemple le plus flagrant est dans le cas d’option.

Dans le screenshot ci-dessus par exemple, le lien « ajouter une option » exécute une fonction javascript qui ajoute trois champs permettant de remplir une option supplémentaire.
De même le bouton supprimer enlève l’option juste au dessus.

Ignorons le manque de design.

Afin d’avoir quelque chose de propre, nous pouvons utiliser l’attribut index. Ainsi, pour un champ de texte de base, nous pouvons allons avoir :

<%= f.text_field :modele, :champ, :index => identifiant %>

Ou identifiant est un nombre unique qui caractérise l’entrée.
En ajoutant cela à tous vos champs, ceux-ci ressembleront à cela :

<input id="modele_1_champ" name="modele[1][champ]" size="30" type="text" />

Dans votre contrôleur, vous n’aurez alors plus qu’à faire quelque chose comme :
params[:modele].each do |modele|
@modele = Modele.new(modele)
@modele.save()
end

C’est cool, ça fonctionne :-)
Cependant c’est tout pas beau car on répète inutilement un identifiant à chaque fois.
Et c’est la que fields_for fait son apparition.
Remplaçons le code précédent :

<% fields_for :modele, variable, :index => identifiant do |f| %>
<%= f.text_field :name %>
<% end %>

Ou variable est une variable qui contiendra la à attribuer à chacun de nos champs, obtenue par :
variable = Modele.find(:all)

Nous définissons une boucle permettant de déclarer de multiples champs avec un index et ce sans répéter celui-ci :-)

Note : un bug qui a été corrigé en juin 2008 apporte un bug avec les listes de sélection, ne leur déclarant pas d’identifiant.
Pour le corriger, il faut remplacer le fichier (sous Windows) <emplacement vers Aptana>/org.jruby_1.1.0.5965_RC2p2/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view\helpers par celui-ci.

 
Fork me on GitHub