adding nested attributes with checkboxes in rails 4 using mass assignment
Asked Answered
I

1

13

error:

param is missing or the value is empty: color

I am making a form where I can add nested attributes to a parent record and I want to add them through checkboxes. I have the parent model "Car" and the child model "Colors"…but I want to start with some default "colors"…so I also have the model "Sample_Colors", which changes based on the "Car_Models".

I am trying to add multiple "Colors" to an associated "Car" using checkboxes…I do NOT want a HABTM relationship with "Sample_Colors" and "Colors", as I need the "Colors" record to be editable and not just a join table. I have done this using HABTM, and so I don't really understand why I can't create a non-join-table record in a similar way.

Where I'm having trouble is with the mass assignments...it either throws the error above or can't find the colors_id...

to clarify what I'm trying to do:

The checkboxes need to
1. Create a new "Color" Record (@color.new) that is associated with the @car record parent
2. Set the "value_one" column of the @color.new record to the sample_color.value_one value
3. Set the "value_two" column of the @color.new record to the sample_color.value_two value

4. The amount of checkboxes that are created == the @sample_colors that are iterated.

car_model.rb

class CarModel
has_many :sample_colors, dependent: :destroy
has_many :cars, dependent: :destroy

car.rb

class Car   
has_many :colors, dependent: :destroy
belongs_to :car_model
accepts_nested_attributes_for :colors, allow_destroy: true

sample_color.rb

class SampleColor
belongs_to :car_model

color.rb

class Color
belongs_to :car
accepts_nested_attributes_for :finishes, allow_destroy: true

_form (for adding colors)

    <%= form_for @car do |f| %>

    <%= f.fields_for 'car[color_attributes][]', @color, index: nil do |f| %>

<label class="form-label dk-aqua">Colors for <%= @car.car_name %></label><br>
<div class="row ">

 <%= hidden_field_tag "car[color_ids][]", nil %>
 <% @sample_colors.each do |sample_color| %>
   <%= check_box_tag "car[color_ids][]", "#{sample_color.id}"  %>  
   <%= hidden_field_tag "car[color_value_ones][]", "#{sample_color.value_one}" %> 
   <%= hidden_field_tag "car[color_value_twos][]", "#{sample_color.value_two}" %> 
   <%= label_tag :value_one, "#{sample_color.value_one}" %>  <br>

 <% end %>
</div>
 <% end %>

    <%= f.submit 'SAVE CHANGES',  :class => 'btn btn-green btn-lg btn-block' %>  
    <%end%>

cars_controller.rb

  def update
    @color = Color.new(color_params)
    @car.color_ids = params[:car][:color_ids] || []
    @car.color_value_ones = params[:car][:color_value_ones] || []
    @car.color_value_twos = params[:car][:color_value_twos] || []
        respond_to do |format|
      if @car.update(car_params)
        format.html { redirect_to @car, notice: 'Car was successfully updated.' }
        format.json { render :show, status: :ok, location: @car }
      else
        format.html { render :edit }
        format.json { render json: @car.errors, status: :unprocessable_entity }
      end
    end
  end

   def car_params
  params.require(:car).permit(:id, :car_name, :car_model_id, colors_attributes: [:id,  {:color_ids => [], :color_value_ones => [], :color_value_twos => []},  :value_one, :value_two,
  finishes_attributes: [:id, :value_one] ]  )
end

def color_params
  params.require(:color).permit(:id,  {:color_ids => [], :color_value_ones => [], :color_value_twos => []},  :value_one, :value_two,
  finishes_attributes: [:id, :value_one]  )
end
Idioblast answered 18/6, 2015 at 14:26 Comment(1)
Please let me know how I can improve a question. I'm newish and I don't want to clog Stackoverflow with poor questions, but sometimes I don't know enough to know why it's bad. I built a sample app to be as thorough as I could on this question...which has dogged me for a week.Idioblast
B
2

You could try replacing:

<% @sample_colors.each do |sample_color| %>
   <%= check_box_tag "car[color_ids][]", "#{sample_color.id}"  %>  
   <%= hidden_field_tag "car[color_value_ones][]", "#{sample_color.value_one}" %> 
   <%= hidden_field_tag "car[color_value_twos][]", "#{sample_color.value_two}" %> 
   <%= label_tag :value_one, "#{sample_color.value_one}" %>  <br>

 <% end %>

With collection_check_boxes:

<%= f.collection_check_boxes(:color_ids, @sample_colors, :id, :value_one) %>

I'm not entirely sure this is correct but it should be a step in the right direction. Let me know how it goes. 🍻

Brownedoff answered 20/6, 2015 at 16:31 Comment(6)
Hmmm... it gives me "undefined method `value_two' for #<SampleColor:0x007f85457ca8b8> " ...maybe this means that you can't fold multiple hidden fields into one checkbox_collection? I tried just using :value_one ... can you even set multiple column values with one checkbox?Idioblast
I'm not entirely sure I understand why to do that, but I updated it so you should at least get a checkbox for each color. :) I'm sorry if I'm dense here, but shouldn't you be able to get the color values by the color relationship once you've added the color ids to the car object? Again, sorry for my misunderstanding.Brownedoff
...I am trying to do something a bit strange...I want to have 1 check_box for each 'sample_color' iteration and checking that box creates a NEW 'color' record with the :id, :value_one (what the label & sample_color.value_one says) and :value_two (what sample_color.value_two says). the colors table is not a join...I just need a way to create color.value_one and color.value_two from the respective templates of sample_color.value one and sample_color.value_two.Idioblast
with the changes it says: "undefined method `value_one' for #<SampleColor:0x007f85456a3a48>"Idioblast
Does your sample color object have an attribute called value_one? I got that from your question's code.Brownedoff
yes, both sample_color and color have an attribute called "value_one" and an attribute called "value_two" . I am using the sample_color objects to set the defaults values for color objectsIdioblast

© 2022 - 2024 — McMap. All rights reserved.