Search code examples
ruby-on-railsnested-attributes

Avoiding blank values in form when updating a model with Nested Attributes


I have an app where Users can choose their favorite colors.

The models are as shown below. Essentially the model UserColor is a simple mapping between a User and a Color

class User < ActiveRecord::Base
  has_many :colors, dependent: :destroy
  accepts_nested_attributes_for :colors, allow_destroy: true
end

class UserColor < ActiveRecord::base
  belongs_to :user
  belongs_to :color
end

class Color < ActiveRecord::Base
end

I have a simple form that lets users choose up to 3 colors from 3 drop down forms (assume repetition of colors is ok). The form is submitted and updated with nested attributes, and essentially just creates (up to) 3 UserColor records.

I filter the params for update in my controller as follows:

params.require(:user).permit(
  colors_attributes: [
    :id,
    :color_id,
    :_destroy
  ]
)

How to avoid blanks?

If the user only selects 1 color, the 2nd and 3rd drop downs are still blank. The nested hash gets submitted as below (no "id" attributes because it's a new record at this point, but otherwise it would have one)

{
  "colors_attributes"=> {
    "0"=>{"color_id"=>"17", "_destroy"=>""},
    "1"=>{"color_id"=>"", "_destroy"=>""},
    "2"=>{"color_id"=>"", "_destroy"=>""}
  }
}

This is unacceptable because the last two records have blank color_id values, which violates a non-null criteria on that field and fails my model save validation.

Is there a good way to filter out or avoid blanks here? I can obviously hack around it by looping through and removing blanks, but is there a more "rails way" accepted way to handle this?


Solution

  • Use the :reject_if option.

    From http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html (with your models):

    accepts_nested_attributes_for :colors, reject_if: proc do |attributes|
      attributes['color_id'].blank?
    end