I've looked through every post I can imagine regarding this, but can't come across a solution. I have a Task with a nested resource of Task Products which grabs its ID's from another database. There can be multiple Task Products nested in a Task, and each one is dynamically created with some Javascript and an Application Helper (both of which are purely a copy/paste on my part).
I built up the code for these nested parameters with the help of Railscast 196/197 and this post. All the relevant code is below, and then onto the problem:
task.rb:
class Task < ApplicationRecord has_many :task_products, :dependent => :destroy accepts_nested_attributes_for :task_products, :reject_if => lambda { |p| p.values.all?(&:blank?) }, :allow_destroy => true end task_controller.rb:
class TasksController < ApplicationController def new @task = Task.new @task.task_products.build end def task_params params.require(:task).permit(:id, :task_name, . . ., :created_at, :updated_at, :task_products_attributes => [:task_id, :product_id, :created_at, :updated_at]) end application_helper.rb:
module ApplicationHelper def new_child_fields_template(form_builder, association, options = {}) options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new options[:partial] ||= association.to_s.singularize options[:form_builder_local] ||= :f content_tag(:div, :id => "#{association}_fields_template", :style => "display: none") do form_builder.fields_for(association, options[:object], :child_index => "new_#{association}") do |f| render(:partial => options[:partial], :locals => { options[:form_builder_local] => f }) end end end application.js:
$(function() { $('form a.add_child').click(function() { var association = $(this).attr('data-association'); var template = $('#' + association + '_fields_template').html(); var regexp = new RegExp('new_' + association, 'g'); var new_id = new Date().getTime(); $(this).parent().before(template.replace(regexp, new_id)); return false; }); }); _form.html.erb:
<%= form_for @task, url: tasks_path, method: :post, :html => {:multipart => true } do |f| %> <%= f.fields_for :task_products, TaskProduct.new do |builder| %> <%= render "task_product", :f => builder %> <% end %> <p><%= add_child_link "Add Product", :task_products %></p> <%= new_child_fields_template f, :task_products %> _task_product.html.erb:
<div class="fields"> <div class="form-group"> <%= f.label :product_id, "Product:", class: 'col-sm-3 control-label' %> <%= f.collection_select(:product_id, @items, :id, :item_select, {:include_blank => 'Select Item...'}, {:class => 'form-control'}) %> <%= remove_child_link "Remove Product", f %> </div> </div> Code in console after submit along with the error it produced:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"KDQ...8bxur2A==", "task"=>{"task_type"=>"Store Order", "task_products_attributes"=>{ "0"=>{"product_id"=>"1", "_destroy"=>"false"}, "1484792726712"=>{"product_id"=>"2", "_destroy"=>"false"}, "new_task_products"=>{"product_id"=>"", "_destroy"=>"false"}}, "initiated_by"=>"1", "initiated_for"=>"5", "active"=>"true", "status"=>"Pending Acceptance"}, "commit"=>"Create Task"} Unpermitted parameters: 0, 1484792726712, new_task_products Generated HTML examples of error producing code of multiple generated selects:
<select class="form-control" name="task[task_products_attributes][0][product_id]" id="task_task_products_attributes_0_product_id"> <select class="form-control" name="task[task_products_attributes][1484794199756][product_id]" id="task_task_products_attributes_1484794199756_product_id"> and its template, which I thought should be throwing back ' "_destroy"=>true' in the console?:
<select class="form-control" name="task[task_products_attributes][new_task_products][product_id]" id="task_task_products_attributes_new_task_products_product_id"> The problem, as seen above, is that my generated Task Product form is adding an additional bracketed identifier(child index?) into my select box for each item, and I don't know how to dive into the Application Helper to remove it, or move it where it belongs. Or does it actually belong there and I'm doing something else wrong? I get the feeling that each individual Task Product should have it's own unique identifier, but Rails isn't having any of that and says its unpermitted.
The 'new_child_fields_template' in the Application Helper is a bit over my head, and while I understand how it's getting the unique identifier to inject into my Task Product form, I don't know how it's throwing it into the "name=" field of my select that is apparently screwing everything up. Anybody have some guidance on how I can overcome this problem? Thanks!
CTRL+Fand search forinclude_hiddenon this page:http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html. You can use that as a param in the#collection_check_boxes.= collection_check_boxes(:object, :field, [opts], :method1, :method2, {include_hidden: false}, ... &block