【问题标题】:Nested form params not working due to strong parameters由于强大的参数,嵌套表单参数不起作用
【发布时间】:2013-09-05 17:30:18
【问题描述】:

我有一个模型声明,它有很多成本:

class Declaration < ActiveRecord::Base
  has_many :costs
  accepts_nested_attributes_for :costs
end

class Cost < ActiveRecord::Base
  belongs_to :declaration
end

我想要一个有 10 条成本行用于声明的表单,因此在声明控制器中我有以下内容,其中包含用于强参数的许可参数:

  def new
    @declaration = Declaration.new
    @costs = Array.new(10) { @declaration.costs.build }
  end

  def create
    @declaration = Declaration.new(declaration_params)
    if @declaration.save
      redirect_to user_declarations_path, notice: I18n.t('.declaration.message_create')
    else
      render action: "new"
    end
  end

  private

  def declaration_params
    params.require(:declaration).permit(:approval_date, :submit_date, :status, :user_id, :declaration_number,
      costs_attributes: [:id, :description, :amount_foreign, :rate, :amount, :cost_date, :projectuser_id])
  end

当然还有表单,所以当我提交表单时,我会在日志中看到:

Started POST "/users/3/declarations" for 127.0.0.1 at 2013-09-05 19:12:38 +0200
Processing by DeclarationsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"mhaznOuBy/zj7LA/nIpDTy7X2u5UrR+0jleJsFid/JU=", "declaration"=>{"user_id"=>"3", "cost"=>{"cost_date(3i)"=>"", "cost_date(2i)"=>"", "cost_date(1i)"=>"", "projectuser_id"=>"", "description"=>"", "amount_foreign"=>"", "rate"=>"", "amount"=>""}}, "commit"=>"Opslaan", "user_id"=>"3"}
  User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 3 ORDER BY "users"."id" ASC LIMIT 1
Unpermitted parameters: cost

那么为什么我会得到一个未经允许的参数cost??

更新:声明表格添加如下:

- if can? :create, Declaration
  = form_for [current_user, @declaration] do |f|
    = f.hidden_field :user_id, value: current_user.id

    .row
      .page-header
        .span7
          %h1.title
            %i{ class: "icon-coffee icon-large" }
            = I18n.t('.declaration.add_title')
        .span5
          .action
            - if can? :create, Declaration
              = link_to I18n.t('.general.cancel'), user_declarations_path(current_user), class: 'btn'
              = f.submit(class: 'btn', value: I18n.t('.general.save'))
    .row
      .span12
        = render "layouts/error_messages", target: @declaration

    .row
      .span12
        = render "form", f: f

以及呈现的形式:

.row
  .span12
    %table.table.table-striped#declarations
      %thead
        %tr
          %th= I18n.t('.cost.cost_date')
          %th= I18n.t('.cost.project')
          %th= I18n.t('.cost.description')
          %th= I18n.t('.cost.amount_foreign')
          %th= I18n.t('.cost.rate')
          %th= I18n.t('.cost.amount')
      %tbody
        - @costs.each do |cost|
          = f.fields_for cost, html: { class: "form-inline"} do |c|
            %tr
              %td{ "data-title" => "#{I18n.t('.cost.cost_date')}" }= c.date_select :cost_date, { include_blank: true, default: nil }
              %td{ "data-title" => "#{I18n.t('.cost.project')}" }= c.collection_select :projectuser_id, @projectusers, :id, :full_name, include_blank: true
              %td{ "data-title" => "#{I18n.t('.cost.description')}" }= c.text_field :description, class: "input-large"
              %td{ "data-title" => "#{I18n.t('.cost.amount_foreign')}" }= c.text_field :amount_foreign, class: "input-small", type: :number, step: "any"
              %td{ "data-title" => "#{I18n.t('.cost.rate')}" }= c.text_field :rate, class: "input-small", type: :number, step: "any"
              %td{ "data-title" => "#{I18n.t('.cost.amount')}" }= c.text_field :amount, class: "input-small", type: :number, step: "any"

有许可证!我收到此错误消息:

Started POST "/users/3/declarations" for 127.0.0.1 at 2013-09-09 09:29:44 +0200
Processing by DeclarationsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"jQwy7psQwixneWF8DezrR/Wo5VKU/dpfz+sosiatm9c=", "declaration"=>{"user_id"=>"3", "cost"=>{"cost_date(3i)"=>"", "cost_date(2i)"=>"", "cost_date(1i)"=>"", "projectuser_id"=>"", "description"=>"", "amount_foreign"=>"", "rate"=>"", "amount"=>""}}, "commit"=>"Opslaan", "user_id"=>"3"}
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 3 ORDER BY "users"."id" ASC LIMIT 1
Completed 500 Internal Server Error in 6ms

ArgumentError - wrong number of arguments (6 for 0):
  app/controllers/declarations_controller.rb:70:in `declaration_params'
  app/controllers/declarations_controller.rb:21:in `create'

【问题讨论】:

  • 您可以为表单发布您的 html.erb 吗?
  • 另外,您能否通过将params.require(:declaration).permit... 更改为params.require(:declaration).permit! 来进行一些故障排除,看看会发生什么?我还没有研究过.permit! 方法,觉得它在生产中使用起来足够安全,但它会突出显示 Rails 单数/复数中是否有问题,即成本与成本......
  • 可能是基于从表单中获取三个参数"cost"=&gt;{"cost_date(3i)"=&gt;"", "cost_date(2i)"=&gt;"", "cost_date(1i)"=&gt;"" 拒绝整个成本哈希?将 cost_date(1i) 识别为 :cost_date 参数?
  • 有许可证!它返回:“参数数量错误(0 为 6)”?

标签: ruby-on-rails-4


【解决方案1】:

第一印象是您返回了三个 cost_date 参数。我认为这需要作为数组返回。您的参数将是:

 def declaration_params
 params.require(:declaration).permit(:approval_date, :submit_date, :status, :user_id, :declaration_number,
  costs_attributes: [:id, :description, :amount_foreign, :rate, :amount, :projectuser_id, :cost_date =>[]])
end

然后,您的网络服务器不再返回:

... "cost"=>{"cost_date(3i)"=>"", "cost_date(2i)"=>"", "cost_date(1i)"=>"",... 

它应该得到:

"cost"=>{"cost_date"=>["","",""],...

虽然没有看到表格,但我不知道这是否是您想要实现的目标。

【讨论】:

  • 我已添加视图
  • 另外,你试过上面的代码吗?您是否应该返回 3 个不同的 cost_date() 参数?这对于表格行来说似乎很奇怪。
  • cost_date 似乎不是这里的问题。
【解决方案2】:

似乎要改变这个:

  - @costs.each do |cost|
      = f.fields_for cost, html: { class: "form-inline"} do |c|

到这里:

= f.fields_for(:costs) do |c|

成功了,因为现在所有的成本记录都被保存了。在控制器中我现在有这个:

@declaration = Declaration.new
10.times do |n|
  @declaration.costs.build
end

我现在剩下的唯一问题是它保存了空的成本记录。

【讨论】:

  • 使用10.times do 无论如何都会给你十个新记录。您应该使用.each 方法。即costs.each do...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 2018-07-12
  • 1970-01-01
  • 2015-09-20
相关资源
最近更新 更多