addressable
addressable copied to clipboard
Type mismatch causes Addressable::URI#query_values= to fail on sort! with "comparison of Array with Array failed"
If the data passed to query_values=
results in a type mismatch in the value of new_query_values
on line 1504 when .sort!
is called, such as:
[['a', '1'], ['a', 2]]
the method will fail with ``sort!': comparison of Array with Array failed`
I'd submit a PR fix myself, but I'm not sure what the desired solution is.
What version of Addressable are you using? I can't duplicate.
2.3.2
Maybe need to make sure you're passing a hash into query_value=
Nope, still can't duplicate. Provide a minimal working example of the bug please.
Try this:
1.9.3p194 :002 > require 'addressable/uri'
=> true
...
1.9.3p194 :006 > uri = Addressable::URI.parse('http://example.com/?page=1')
=> #<Addressable::URI:0x3fd3f85b8b30 URI:http://example.com/?page=1>
1.9.3p194 :007 > uri.query_values = uri.query_values.merge(:page => 2)
ArgumentError: comparison of Array with Array failed
from /Users/shannoncarey/.rvm/gems/ruby-1.9.3-p194@hermes-frontend/gems/addressable-2.3.2/lib/addressable/uri.rb:1504:in `sort!'
from /Users/shannoncarey/.rvm/gems/ruby-1.9.3-p194@hermes-frontend/gems/addressable-2.3.2/lib/addressable/uri.rb:1504:in `query_values='
from (irb):7
from /Users/shannoncarey/.rvm/gems/ruby-1.9.3-p194@hermes-frontend/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
from /Users/shannoncarey/.rvm/gems/ruby-1.9.3-p194@hermes-frontend/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start'
from /Users/shannoncarey/.rvm/gems/ruby-1.9.3-p194@hermes-frontend/gems/railties-3.2.9/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
The problem here is query_values always returns a hash keys and values as strings after the parse, and then {"page" => "1"}.merge({:page => 2}) --> {"page" => "1", :page => 2}
that code in lib/addressable/uri.rb:197
new_query_values = new_query_values.to_hash
new_query_values = new_query_values.map do |key, value|
key = key.to_s if key.kind_of?(Symbol)
[key, value]
end
The new_query_values has [["page", "1"], ["page", 2]] and when use new_query_values.sort! first sort by first value (the keys) and if are equal, sort by the second values (the hash values), but you can't compare String with Integer.
Could you write a test that reproduces this problem?
I'll have one for you shortly.
See associated PR.
Thank you, that helps a lot.
Had the same issue, solved by stringify_keys
; but I think this one should be solved inside addressable it self.
@dmitry It's come up before and as before, the answer is essentially no, won't fix. If Ruby adds an indifferent access hash structure to the standard library, I'll revisit that answer, but until then, I prefer for this kind of usage to be explicitly controlled by the user of the library, exactly as you're doing. I strongly argue that principle of least surprise was violated when Rails introduced this pattern in the first place and I reject the idea that once they made bad behavior commonplace that suddenly good behavior became "surprising".
@sporkmonger I agree, but in that case the small note should be added to the documentation, as keys should be strings, and not symbols because of the ambiguous while sorting and forming the query. Somewhere here:
https://github.com/sporkmonger/addressable/blob/master/lib/addressable/uri.rb#L1607