2014-03-19 40 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有效)。