From ea40dc09a564ebc2b0034e3c1ae2c4daffe7e79b Mon Sep 17 00:00:00 2001
From: Xavier Noria <fxn@hashref.com>
Date: Tue, 17 Jun 2008 21:59:41 +0200
Subject: provide a more complete explanation about why the check_box generates
 a hidden field, and document the problem with array-like parameters

---
 actionpack/lib/action_view/helpers/form_helper.rb | 33 +++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

(limited to 'actionpack')

diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 7d85799038..6348ff5f49 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -449,8 +449,37 @@ module ActionView
       # assigned to the template (identified by +object+). It's intended that +method+ returns an integer and if that
       # integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a
       # hash with +options+. The +checked_value+ defaults to 1 while the default +unchecked_value+
-      # is set to 0 which is convenient for boolean values. Since HTTP standards say that unchecked checkboxes don't post anything,
-      # we add a hidden value with the same name as the checkbox as a work around.
+      # is set to 0 which is convenient for boolean values.
+      #
+      # === Gotcha
+      #
+      # The HTML specification says unchecked check boxes are not successful, and
+      # thus web browsers do not send them. Unfortunately this introduces a gotcha:
+      # if an Invoice model has a +paid+ flag, and in the form that edits a paid
+      # invoice the user unchecks its check box, no +paid+ parameter is sent. So,
+      # any mass-assignment idiom like
+      #
+      #   @invoice.update_attributes(params[:invoice])
+      #
+      # wouldn't update the flag.
+      #
+      # To prevent this the helper generates a hidden field with the same name as
+      # the checkbox after the very check box. So, the client either sends only the
+      # hidden field (representing the check box is unchecked), or both fields.
+      # Since the HTML specification says key/value pairs have to be sent in the
+      # same order they appear in the form and Rails parameters extraction always
+      # gets the first occurrence of any given key, that works in ordinary forms.
+      #
+      # Unfortunately that workaround does not work when the check box goes
+      # within an array-like parameter, as in
+      #
+      #   <% fields_for "project[invoice_attributes][]", invoice, :index => nil do |form| %>
+      #     <%= form.check_box :paid %>
+      #     ...
+      #   <% end %>
+      #
+      # because parameter name repetition is precisely what Rails seeks to distinguish
+      # the elements of the array.
       #
       # ==== Examples
       #   # Let's say that @post.validated? is 1:
-- 
cgit v1.2.3