ActionView::Helpers::FormTagHelper.check_box_tag should be more helpful (like ActionView::Helpers::FormHelper.check_box)

Hi folks,

You start with something like this:

<%= check_box_tag :foo, 1 %>

<%= label_tag :foo, "Foo?" %>

The logic may be broken if you expect the unchecked state to arrive in a param on the server. But a11y-wise the example is OK.

You discover the logical error (Maybe google leads you to the “Gotcha” that f.check_box smooths over for us at . A sensible place to look since generally in Rails the f.* methods have corresponding *_tag methods to be used independently of a form builder).

And you think “Well that’s no big deal, I’ll just add the hidden input myself”, right? And you wind up with this:

<%= hidden_field_tag :foo, 0 %>

<%= check_box_tag :foo, 1 %>

<%= label_tag :foo, "Foo?" %>

Now there’s a subtle a11y bug where the label is no longer hooked up to the checkbox, since by default hidden_field_tag generates an an id of “foo” (anti-a11y behavior observed in Chromium 43 and Iceweasel 31 (incidentally, this browser behavior is contrary to my interpretation of Note 2 of Once again, this is an issue that f.check_box takes care of for you.

We should address this because

  1. Current check_box_tag behavior lends itself to “gotcha” logical errors

  2. Most obvious solution to “gotcha” error leads to subtle a11y bug

  3. Dissonance between f.checkbox and check_box_tag violates Rails’ pattern of f.* methods having corresponding *_tag methods.

Solutions I can think of

a) Deprecate check_box_tag completely

b) Make check_box_tag automatically generate the same perfect hidden input that f.check_box generates

  • This would be a breaking change, and there is no precedence for a *_tag method generating more than a single HTML element, but if f.checkbox is special, maybe check_box_tag should be special, too?

c) Offer an option on check_box_tag fix_gotcha: true that is well-documented and generates the perfect hidden input

  • We can later output a deprecation warning on check_box_tags with no value for fix_gotcha: “fix_gotcha will default to true on future versions, please add fix_gotcha: false to opt out of this behavior”