rails: Strong parameters doesn't permit array of arrays (nested arrays)

Hey guys,

When I tried to permit params that contains an Array of Array, strong parameters permit is ignoring the second Array and returning an empty Array.

Example:

Controller

params.permit(param1: [param2: [[[:attr, :op, :val]]]])

Sent Parameters

"param1": {"param2": [[{"attr": "1", "op": "<", "val": "2"}]]}

Rails will ignore the nested Arrays and will return only the {param1: [] }

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 37
  • Comments: 28 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Guys, seriously, two years to fix an issue of this magnitude? I can’t send my quite normally-structured data to a Rails controller? Surely that’s high on the priority list for fixing?

Sorry but bumping to get attention is also disrespectful, a lot. My give a lot of our time for free to people, and we do that because we like, but nobody likes when people is poking you to get something that you are not ready to give.

And just to be clear I was not being ironic. I was being really direct, bumping just annoy and cause people to avoid to review the PR and will not get anything fixed. I was not being disrespectful either, they are, with the maintainers and with the contributor that spent time to fix the problem.

You don’t enter a working kitchen and ask the chef to hurry because you are hungry.

I’m sorry that the review took so long, but as you may have noticed Rails is made by volunteers and they have life, in the same way that the contributors. Maintainers don’t poke people to update they PRs or issues in respect to their time and life, so we expect the same respect from the contributors.

Focusing in the solution of the problem, ee are still in doubt about the implementation:

It just fixes a problem with the nested array pattern, like: [[{ a: :b }], [{ b: :c }]] it does not add a new pattern.

Is not an answer for the question made. The question is: do this change now start to permit something that was not permitted before?

We get that it add a new pattern, but does that means that no existing pattern would change its behavior? Or they would?

To give an example, would params.permit(foo: []) have its behavior changed?

@rafaelfranca same here https://github.com/rails/rails/pull/23650#issuecomment-367178282 It has been 2 years you guys are passing this PR to another one, so please instead come here and be ironic with the guys, how about have respectful with the work and time spent to get it working and answer the question, or just review the PR? if you guys really believe in your words about hey, come here and contribute to rails, we really enjoy you guys work, I sorry to say, you are doing this wrong.

Any updates about this 😄 ?

Hi all, I’m curious why I am able to create a nested array but during the rails controller request, the nested array gets flattened? <ActionController::Parameters {"components"=>[["abc", "123"], ["def", "456"]]} permitted: true>

Guys, please, fix this issue, it would be great

I think the guys are just discrediting that this PR will be reviewed and merge, once took almost 1 year to have a review. What I expect from a rails team guy, instead to spent time going here to be “direct” with an irrelevant comment ( looking through code and PR ) is to go to PR and comment, to review it I need that X answer the question or something like that. but that’s ok, I think the focus should be to get it merged.

Answering the question, I really don’t know, I have not more rails env setuped on my environment, and have no much time to get it done right now. so, if you want to close this PR, and allow another one to open a new PR with the code, could do without worries

helloooooo… bump!

hello guys, the PR is already updated with changes requested by rails team, just waiting review please follow: https://github.com/rails/rails/pull/23650

Thanks,

I ran into this problem today. Any updates on when this will be approved and merged?

@alexanderfrankel

Yes the PR is still open, is need someone from rails team review it.

I will comment again on PR and try that someone review it.

I want to propose another syntax:

We currently don’t have any symbol to indicate if we permit an array or an object. [] in strong parameter’s semantics only has one meaning at this point: a list of permitted attributes. It can not be used to decide the permitted params’ structure.

param1 = ActionController::Parameters.new(book: { title: "foo"  })
param1.permit(book: [:title]).to_h 
#=> {"book"=>{"title"=>"foo"}}
param2 = ActionController::Parameters.new(book: [{ title: "foo"  }])
param2.permit(book: [:title]).to_h
#=> {"book"=>[{"title"=>"foo"}]}

Here’s how we use an [] now, if it contains

  • symbols: only permit these attributes
  • hashes: only permit hash keys attributes and resolve those attributes’ attributes
  • nothing: permit anything/any key

As you can see, it requires names (symbol or hash key) to make it work. This means [[:title]] breaks the rule by not providing names. And since books: [:title] means permitting a single object/a collection of objects with title. I say we follow that rule, which is providing a name to declare what we’re doing. This means using something like books: {[] => [:title]} to declare that we permit an array of a single object/a collection of objects with title. So it will permit both of

{
  "books" => [{ title: "foo" }]
}

And

{
  "books" => [
    [{ title: "foo" }]
  ]
}

So back to the issue example: {"param1": {"param2": [[{"attr": "1","op": "<", "val": "2" }]] }}

I think we should use permit(param1: [param2: {[] => [:attr, :op, :val]}])

And it’ll be:

params = {
  "param1": {
    "param2": [
      [{"attr": "1","op": "<", "val": "2" }]
    ] 
  }
}

params.permit(param1: [param2: {[] => [:attr, :op, :val]}])

Please update that.

when you want to permit books array of hash:

{
  "library": {
    "name" : "my library",
    "books": [{ title: "foo", author: "John" }, { title: "foo", author: "James" }]
  } 
}

This code should work:

params.require(:library).permit(:name, books: [:title, :author])

Important: You need to write hash index (:title, :author) in books array in permit. This way you can permit more nested attributes.

params.require(:order).permit(:recipient_name, :recipient_phone,
        order_items_attributes: [:id, :product_name, :_destroy, product_addons: [:name, :option, :price]])

Here product_addons is an Array of Hash. I used this code in a Rails 5 project for nested form and it works!

Thanks @st0012

bumping the issue will not get it fixed 😄! If you want to get his fixed answering those questions is the way to go https://github.com/rails/rails/pull/23650#issuecomment-374824879