Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strong parameters with nested hash

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?

like image 720
Topher Fangio Avatar asked Sep 24 '15 16:09

Topher Fangio


1 Answers

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.

like image 76
DickieBoy Avatar answered Sep 30 '22 01:09

DickieBoy