2014-03-19 102 views
0

与simple_form嵌套的has_many关联返回以下PARAMS散列:嵌套形式simple_form和强参数

params 
# => { 
     "user"=>{ 
     "first_name"=>"John", 
     "last_name"=>"Doe", 
     "bank_accounts_attributes"=>{ 
      "-1"=>{ 
      "_destroy"=>"0", 
      "iban"=>"fakeiban", 
      "bic"=>"fakebic" 
      }, 
      "new-bank-account"=>{ 
      "_destroy"=>"0", 
      "iban"=>"", 
      "bic"=>"" 
      } 
     } 
     } 
    } 

关键的“-1”是通过复制创建新的,目前还没有持久的bank_accout“新 - 银行账户“模板(由于iban为空白,因此被忽略)。

我该如何准许这些强参数?

我已经尝试了以下无济于事:

permitted_params = { 
    :first_name, 
    :last_name, 
    { 
    :bank_accounts_attributes=>[:iban, :bic] 
    } 
} 

params.require(:user).permit(*permitted_params) 
Unpermitted parameters: -1, new-bank-account 
# => { 
     "user"=>{ 
     "first_name"=>"John", 
     "last_name"=>"Doe", 
     "bank_accounts_attributes"=>{} 
     } 
    } 

什么我错在这里做什么?

UPDATE:

下工作,但我不想列入负面键(其代表非持久的关系)到处明确:

params.require(:user).permit(:first_name, :last_name, bank_accounts_attributes: {"-1" => [:iban, :bic]}) 

更新2:

问题似乎是“新银行帐号”键:

p = ActionController::Parameters.new user: { first_name: "Foo", bank_accounts_attributes: {"-1" => {iban: 'xxx'}, "-2" => {iban: 'yyy'}}} 
p.require(:user).permit(:first_name, bank_accounts_attributes: :iban) 
# => {"first_name"=>"Foo", "bank_accounts_attributes"=>{"-1"=>{"iban"=>"xxx"}, "-2"=>{"iban"=>"yyy"}}} 

p = ActionController::Parameters.new user: { first_name: "Foo", bank_accounts_attributes: {"-1" => {iban: 'xxx'}, "new-bank-account" => {iban: 'yyy'}}} 
p.require(:user).permit(:first_name, bank_accounts_attributes: :iban) 
# => {"first_name"=>"Foo", "bank_accounts_attributes"=>{}} 

看来我必须在提交表单之前从DOM中删除模板“new-bank-account”。

+0

您的用户模型中是否有'accep_nested_attributes_for:bank_accounts'? – oxtub

+0

是的,我正在加入Rails 4,并在Rails 3上工作。 – svoop

回答

0

我会回答我自己的问题:

强参数只有在它们是整数时才接受has_many键。一个非整数键足以让所有嵌套记录从params散列消失。因此有两种解决方案:

  • 对模板使用非整数键(例如“new-entry”),并在表单提交之前将其从DOM中移除。
  • 如果你像我一样,不想要这个额外的JS代码,使用保留的数字键,例如“999999”作为模板,并确保新的未被执行的嵌套记录不会发生冲突。由于持久记录的键是“0”,“1”等,我们使用一个分配“-1”并倒计数的计数器。另一种方法是时间戳,例如Date.now()(快,但不适用于< = IE8)或+new Date()(较慢,但对IE8有效)。