rails: Nested params are parsed incorrectly (unexpectedly) in controllers
Hi all, I ran into some inconsistency with controller parsing nested params.
Steps to reproduce
post '/', params: {
"items" => [
{ "brand" => { "name" => "Apple" }, "id" =>1, "color" => "pink" },
{ "brand" => { "name" => "Samsung" }, "id" => 2, "color" => "gold" },
]
}
# what appears in controller
{"items"=>[{"brand"=>{"name"=>"Samsung"}, "id"=>"1", "color"=>"pink"}, {"id"=>"2", "color"=>"gold"}]}
https://gist.github.com/simsalabim/6785d3c85bdd20f2e7c5
System configuration
Rails version: 5.0.0.beta3 (current master) Ruby version: 2.3.0
Oddly enough, the gist fails on earlier versions of Rails too (4-2-stable, 4-1-stable), while our production app works fine on 4.2.5.
Could anyone please tell me what I’m missing and where is the best place to start looking for params being processed in a controller action? Thanks.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 26
- Comments: 50 (27 by maintainers)
Commits related to this issue
- Failing test for https://github.com/rails/rails/issues/23997#issuecomment-213117462 — committed to vipulnsward/rack by vipulnsward 8 years ago
- Failing test for https://github.com/rails/rails/issues/23997#issuecomment-213117462 — committed to vipulnsward/rack by vipulnsward 8 years ago
- Use Rack to generate query information under test `to_query` sorts parameters before encoding them. This causes a round tripping issue as noted here: https://github.com/rails/rails/issues/23997#i... — committed to rails/rails by tenderlove 6 years ago
@tak1n I checked your test file https://github.com/tak1n/nested_attributes_reproduction/blob/master/test/integration/book_test.rb but I believe there is an issue because this definitely does work for me (same case) in Rails 5 integration tests but you need to specify
as: :json
there, the format option is for controller tests. Change the code to what you see below and see if it passes:Note that the
as: :json
is a separate hash from params entirely. Has to be separate based on docs. Also while the URL does have.json
at the end I don’t believe that is sufficient as when I first started doing this I looked at what happens under the hood and the test seems to really do certain things based on theas:
option being set. Give it a try and let me know if that works.Okay, after doing quite a bit of digging, I’ve learned that this issue is related to the fact that the the
ActiveSupport
Hash#to_query
extension sorts the query parameters before joining them. When I try removing thesort!
the results show up on the server as expected. It looks likeRack::Utils.parse_nested_query
handles things differently depending on the order of the params. I came across this other issue which looks like the same thing but was closed a couple of years ago.I think we can close this because it was fixed here: https://github.com/rails/rails/pull/33093
If not, lets reopen or make a new ticket. Thanks!
I’m getting something similar in
4.2.5
:This:
Ends up like this:
Is there a working version of rack I could use?
@tenderlove Is there a way to address this issue for Rails 4? I tried the
as
solution and it seems like my endpoint doesn’t detect the params and the headers at all.Using rails 4.2.11.1 with rack 1.6.12
Is there an update on the status of this? It’s still reproducible under Rails 5.1.5 and breaks even if the tests use
format: :json
Update: I missed @javierjulio’s comment above, but switching from
format: :json
toas: :json
fixes the problem.Also referenced in https://github.com/rspec/rspec-rails/issues/1700
Hi all! I’ve stumbled upon a similar problem - not sure if I have to report it as a separate issue.
In short: when submitting multipart form data with hash that has an element with blank value (i.e. blank text field of a form), it doesn’t appear in params (the key is missing). When submitting the same form not as a multipart form data, the field presents in the hash (which is a correct behavior). Attached is a test script demonstrating both scenarios.
Looks like this is Rack issue and it will be fixed soon. Going to keep this open in the meantime.