嵌套属性中未允许的参数

时间:2017-01-19 03:22:52

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4

我已经查看了我能想到的每一篇文章,但无法找到解决方案。我有一个任务,其中包含任务产品的嵌套资源,可从另一个数据库中获取其ID。可以在任务中嵌套多个任务产品,每个任务产品都是使用一些Javascript和一个应用程序助手动态创建的(两者都是我自己的复制/粘贴)。

我在Railscast 196 / 197this post的帮助下为这些嵌套参数构建了代码。所有相关代码都在下面,然后是问题所在:

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>

提交后的控制台中的代码及其产生的错误:

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

生成错误的HTML示例生成多个选择的代码:

<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">

及其模板,我认为应该扔掉&#39; &#34; _destroy&#34; = GT;真&#39;在控制台?:

<select class="form-control" name="task[task_products_attributes][new_task_products][product_id]" id="task_task_products_attributes_new_task_products_product_id">

问题,如上所示,我生成的任务产品表单是在每个项目的选择框中添加一个额外的括号标识符(子索引?),我不知道如何深入了解应用程序帮助将其移除,或将其移动到它所属的位置。或者它实际上属于那里,我做错了什么?我觉得每个单独的任务产品应该拥有它自己的唯一标识符,但是Rails没有任何该标识符,并且说它未被允许。

&#39; new_child_fields_template&#39;在应用程序助手中有点过头了,虽然我理解如何将唯一标识符注入我的任务产品表单中,但我不知道它是如何将其投入到&#34;名称=&#34;我选择的领域显然是搞砸了一切。有人对如何克服这个问题有一些指导吗?谢谢!

2 个答案:

答案 0 :(得分:1)

要使嵌套属性与强属性很好地配合,您需要将id_destroy属性传递给属性列表。在tasks_controller.rb

params.require(:task).permit(
    task_products_attributes: [
        :id, :product_id, :created_at, :updated_at, :_destroy
    ]
)

要获得更清晰的解释,您可以转到此answer

答案 1 :(得分:0)

最后一条评论,除非有人在我的嵌套参数中包含“:id”的原因没有任何额外输入。

我终于通过将允许的参数更改为

来实现它
params.require(:task).permit!  

这显然是对任何恰好落入:task参数的内容的一揽子许可,无论它是否嵌套。我认为这不是推荐的,但它所关注的网站被关闭到很少的团队成员,所以我认为这应该不是问题?此外,我仍在寻找洞察为什么“new_task_products”的模板没有给我一个“destroy =&gt; 1”,因为它应该是,因为product_id是空白的。这段代码不正确吗?

accepts_nested_attributes_for :task_products, 
    :reject_if => lambda { |p| p.values.all?(&:blank?) },
    :allow_destroy => true

我可能会尝试将模板移动到视图之外的某个位置,以避免出现问题。感谢大家的帮助!