'How can I selectively add query parameters in redirect_to?

In my application, the session hash can contain the keys sort and ratings (in addition to _csrf_token and session_id), depending on what action a user takes. That is, it can contain both of them, either one of them, or neither, depending on what a user does.

Now, I wish to call redirect_to in my application and, at the same time, restore any session information (sort or ratings) the user may have provided.

To do this, I want to insert whatever key-value session has currently got stored (out of sort and ratings) as query parameters in my call to redirect_to. So, the path might look something like /movies?sort=...&ratings=....

I don't know how to write the logic for this. How can I do this? And how do I go about selectively inserting query parameters while calling redirect_to? Is it even possible to do this?

Any help is greatly appreciated. Thank you in advance.



Solution 1:[1]

First just compose a hash containing the parameters you want - for example:

opts = session.slice(:sort, :ratings)
              .merge(params.slice(:sort, :ratings))
              .compact_blank 

This example would contain the keys :sort, :ratings with the same keys from the parameters merged on top (taking priority).

You can then pass the hash to the desired path helper:

redirect_to foos_path(**opts)

You can either just pass a trailing hash option or use the params option to explitly set the query string:

irb(main):007:0> app.root_path(**{ sort: 'backwards' })
=> "/?sort=backwards"
irb(main):008:0> app.root_path(params: { ratings: 'XX' })
=> "/?ratings=XX"
irb(main):009:0> app.root_path(params: { })
=> "/"   

An empty hash will be ignored.

If your calling redirect_to with a hash instead of a string you can add query string parameters with the params: key:

redirect_to { action: :foo, params: opts }

If you're working with an arbitrary given URL/path and want to manipulate the query string parameters you can use the URI module together with the utilities provided by Rack and ActiveSupport for converting query strings to hashes and vice versa:

uri = URI.parse('/foo?bar=1&baz=2&boo=3')
parsed_query = Rack::Utils.parse_nested_query(uri.query)
uri.query = parsed_query.except("baz").merge(x: 5).to_query 
puts uri.to_s # => "/foo?bar=1&boo=3&x=5"  

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1