I’d like to generate a URL where the “p=1” query param appears at the end of the URL, like:
/path?foo=X&bar=Y&p=1
Is it possible to control the ordering of query parameters when generating URLs via:
url_for(params.merge({ p: page_num }))
?
Update:
I tried ChuckE’s suggestion below. It turns out that in Ruby 1.9 Hashes are already ordered, so the code in ActiveSupport::OrderedHash is effectively no-op’d. You can verify with Ruby 1.9 that order is preserved:
>> h = {one: 1, two: 2, three: 3 }
{:one=>1, :two=>2, :three=>3}
>> f = h.except(:one)
{:two=>2, :three=>3}
>> f[:one] = 1
1
>> f
{:two=>2, :three=>3, :one=>1}
However, url_for still puts the “p” param first. It seems that any potential solution will need to address how url_for iterates the hash.
After further digging, I see that what’s happening is that
url_foris actually sorting the parameters by key lexicographically, independent of their insertion order in the hash. Apparently this is being done to aid caching, since URL params are often used for page cache keys.In short, you can’t do it without patching
Hash, specifically, you need to overrideactivesupport/core_ext/object/to_param.rbso that Hash#to_param does not call.sorton the return value.Related question: How to generate custom sorted query string URL in Rails link_to?.