Strong parameters with nested hash

£可爱£侵袭症+ 提交于 2019-12-14 00:17:24

问题


I have the following params and cannot get the strong parameters to work.

Here's my basic code, runnable in the Rails console for simplicity:

json = {
  id: 1,
  answers_attributes: {
    c1: { id: "", content: "Hi" },
    c2: { id: "", content: "Ho" }
  }
}

params = ActionController::Parameters.new(json)

Everything I've read says the following should work, but it only gives me the id and an empty hash of answers_attributes:

params.permit(:id, answers_attributes: [:id, :content])
=> { "id"=>1, "answers_attributes"=>{} }

If I instead manually list c1 and c2 (like below) it works, but this is really stupid because I don't know how many answers the user will supply, and this is a lot of duplication:

params.permit(:id, answers_attributes: { c1: [:id, :content], c2: [:id, :content] })
=> {"id"=>1, "answers_attributes"=>{"c1"=>{"id"=>"", "content"=>"Hi"}, "c2"=>{"id"=>"", "content"=>"Ho"}}}

I've tried replacing c1 and c2 with 0 and 1, but I still have to manually supply the 0 and 1 in my permit statement.

How can I permit an unknown length array of nested attributes?


回答1:


It's done with syntax like:

answers_attributes: [:id, :content]

The problem is the keys you are using in the answers_attributes. They are expected to be the ids of the answers_attributes or in the case of new records 0.

Changing these gives your expected outcome:

json = {
  id: 1,
  answers_attributes: {
    "1": { id: "", content: "Hi" },
    "2": { id: "", content: "Ho" }
  }
}

params = ActionController::Parameters.new(json)

params.permit(:id, answers_attributes:[:id, :content])
=>  {"id"=>1, "answers_attributes"=>{"1"=>{"id"=>"", "content"=>"Hi"}, "2"=>{"id"=>"", "content"=>"Ho"}}}

Edit: It appears that 0 is not the only key, I mean what if you have two new records. I use nested_form and it appears to use a very long random number.




回答2:


Your answers_attributes contains c1 and c2 which are not permitted. http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

WAY 1: You can pass the nested attributes as array of hashes.

json = {
  id: 1,
  answers_attributes: [ { id: "", content: "Hi" }, { id: "", content: "Ho" } ]
}

Now params.permit(:id, answers_attributes: [:id, :content]) gives

{"id"=>1, "answers_attributes"=>[{"id"=>"", "content"=>"Hi"}, {"id"=>"", "content"=>"Ho"}]}

WAY 2: You can pass as hash of hashes like

json = {
  id: 1,
  answers_attributes: {
    c1: { id: "", content: "Hi" },
    c2: { id: "", content: "Ho" }
  }
}

Both WAY 1 and WAY 2 have the same effect in the model level. But permit doesn't allow the values to pass unless the keys are explicitly specified. So c1 and c2 will not be permitted unless explicitly specified like

params.permit(:id, answers_attributes: [c1: [:id, :content], c2: [:id, :content]])

which is really a pain in the ass.



来源:https://stackoverflow.com/questions/32766406/strong-parameters-with-nested-hash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!