views:

46

answers:

1

I'm doing maintenance work on an existing rails site and have run into a strange bug. There are a few different models involved here: Registrations, Business Categories, and Services. Registrations HABTM Business Categories and Services, each of which HABTM Registrations. The appropriate non-primary-keyed join tables exist for each of the HABTM relationships.

There's a single form with two sections (one for Business Categories and one for Services) that users fill out to update their registrations. Each of the two sections consists of many checkboxes, one for each potential business category and one for each service. For example, the HAML that generates the business category checkboxes is as follows:

    - BusinessCategory.find(:all, :order => ['business_type']).each do |business_category|
      %li
        = check_box_tag "registration[business_category_ids][]", business_category.id, (@registration.business_categories.include?(business_category)) ? true : false
        = business_category.business_type

In the update function of the Registrations controller:

  @registration = current_user.registration
  if @registration.update_attributes(params[:registration])
    flash[:notice] = "Company Successfully Updated."
    redirect_to :action => 'edit_company'
  else
    ... do appropriate error reporting and redirection ...

In general, everything works fine. Users can sign up with as many or as few boxes checked as they'd like, and their Registration's Business Categories and Services reflect the checked boxes. Subsequent modifications also work, for the most part. However, if at any time users deselect all of the boxes in a given portion (biz categories or services) of the form, none of the changes to that portion of the form are saved. There aren't any error messages, and the flash "Company Successfully Updated" still appears, but the boxes remain checked even though they were unchecked before the form was submitted.

Were I rebuilding/refactoring the site, I'd be more likely to use has_many :through rather than HABTM, but our budget doesn't give me enough time for that. Does anyone have any ideas as to why HABTM seems to have trouble letting go?

Thanks for your consideration!

Justin

A: 

If a checkbox is not selected, then the browser doesn't send anything back for that field. Rails gets around this by including a hidden field with the same name as the checkbox. Rails will then get back either the hidden field alone (box unchecked) or both fields (box checked). The gotcha is that this doesn't work for arrays of checkbox fields. I'm not up on my HAML, but I think this is your problem, and that if no checkbox is checked, there is no :registration key in the params hash, and so nothing is updated.

See the API ref.

Fred
I think you're dead on. Any ideas for working around it?
justinbach
You could test to see if the :registration key exists in the hash, and if not, do the no-checked-boxes thing.
Fred
Thanks, Fred--that's what I did and it works perfectly!
justinbach