rails: to_query used on hash's don't keep order
There is an issue in the to_query function (defined in https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/to_query.rb) for Hash objects.
When to_query is used on an Array, the order of the input array is kept, while when used on a Hash, the order is changed to be lexographical, not what is input (the Hash.to_query is aliased to to_param, see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/to_param.rb)
You can see this by the following:
1.9.3p392 :001 > require 'active_support/core_ext/object/to_query'
=> true
1.9.3p392 :002 > ['c', 'a', 'b'].to_query('foo')
=> "foo%5B%5D=c&foo%5B%5D=a&foo%5B%5D=b"
1.9.3p392 :003 > {'c' => 'b', 'a' => 'c', 'b' => 'a'}.to_query('foo')
=> "foo%5Ba%5D=c&foo%5Bb%5D=a&foo%5Bc%5D=b"
Here, the [‘c’, ‘a’, ‘b’].to_query(‘foo’) goes to “foo[]=c&foo[]=a&foo[]=b” url escaped. Note that the order of 3 1 2 is kept. However, when the input is {‘c’ => 'b, ‘a’ => ‘c’, ‘b’ => ‘a’}.to_query(‘foo’), the output is “foo[a]=c&foo[b]=a&foo[c]=b” url escaped. Note that the order of the original hash keys was c a b, but the output has lexographical of a b c.
I would say this is a bug, as it is inconsistent with the Array to_query, and there is no standard saying that url param queries must be in lexographical order. Ruby hashes keep order, so why break it?
A fix for this is at https://gist.github.com/hughdavenport/5545117
Cheers,
Hugh
About this issue
- Original URL
- State: closed
- Created 11 years ago
- Comments: 19 (6 by maintainers)
Just for the files, you can solve it like this:
query = params.map{|k, v| CGI::escape(k.to_s) + '=' + CGI::escape(v)}.join('&')
The order of query parameters IS significant, even if you saw some software that ignores it during parsing. For example:
Sorting the keys might be useful, and it might even be a reasonable default, but it’s presumptuous for an API to completely remove the ability to specify the order! A bad decision was made here.
My response which was never answered remains…
Yup, I noticed that, this bug was merely as there is a difference between the Array and the Hash invocations. If it should be ordered lexographically, then why not both? and why does it need to be lexographical? as that is just extra work.
All this said, I am aware that the way I am using this is an unusual scenario, but yeh… I would say they should either both be sorted, or both not.
I would open a pull request, but I find that with this community that when I offer a suggestion to fix what myself and a whole lot of other users think is a bug, it gets shut down. The point of an open source community is to allow friendly collaboration. If you would like to discuss why you don’t find what I just wrote above is not a bug, could you? Otherwise why comment at all, just leave the bug tracker stale.
Hugh