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
]
)
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?
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