HABTM Checkboxes, slightly revised

Many folks, including us, have made use of Ryan Bates’ RailsCast on updating HABTM relationships using checkboxes. We use a slightly revised version that is a little more helper-friendly, in that it doesn’t require any controller code.

Explanation first: You need the controller code in the first place because unchecked checkboxes don’t get submitted as part of your form. As a result, when none of a set of checkboxes are checked, your <habtm_assoc>_ids= method won’t get called, and any existing associations won’t get removed. (This is a bit insidious, and can be missed in testing.) To fix it, you need to make sure you end up with an appropriately empty (but non-nil) Array in your params hash.

So, as an alternative to this in your controller:

params[:product][:category_ids] ||= []

you can add an appropriately named nil hidden field in your view:

<!-- products/_form.rhtml -->
<%= hidden_field_tag "product[category_ids][]", nil %>
<% for category in Category.find(:all) %>
<div>
  <%= check_box_tag "product[category_ids][]", category.id, @product.categories.include?(category) %>
  <%= category.name %>
</div>
<% end %>

The hidden field will ensure that association removal happens as you intend it to, but will otherwise be ignored. Yay! Skinnier controllers, a pattern we can helperize, and working checkboxes, and it’s only a slightly ugly hack.

Leave a Reply