225
votes

I'm having difficultly adding querystring parameters to link_to UrlHelper. I have an Index view, for example, that has UI elements for sorting, filtering, and pagination (via will_paginate). The will_paginate plugin manages the intra-page persistence of querystring parameters correctly.

Is there an automatic mechanism to add the querystring parameters to a give named route, or do I need to do so manually? A great deal of research on this seemingly simple construct has left me clueless.

Edit

Some of the challenges:

  1. If I have two querystring parameters, bucket & sorting, how do set a specific value to one of these in a link_to, while preserving the current value of the other? For example:

    <%= link_to "0", profiles_path(:bucket => '0', :sorting=>?? ) %>
    
  2. If I have multiple querystring parameters, bucket & sorting & page_size, and I want to set the value to one of these, is there a way to 'automatically' include the names and values of the remaining parameters? For example:

    <%= link_to "0", profiles_path(:bucket => '0', [include sorting and page_size name/values here] ) %>
    
  3. The will_paginate plugin manages its page variable and other querystring variables automatically. There doesn't seem to be an automatic UI element for managing page size. While I've seen code to create a select list of page sizes, I would rather have A elements for this (like SO). Part of this challenge is related to #2, part is related to hiding/showing this UI element based on the existence/non-existence of records. Said another way, I only want to include page-size links if there are records to page. Moreover, I prefer to automatically include the other QS variables (i.e. page, bucket, sorting), rather than having to include them by name in the link_to.

4

4 Answers

354
votes

The API docs on link_to show some examples of adding querystrings to both named and oldstyle routes. Is this what you want?

link_to can also produce links with anchors or query strings:

link_to "Comment wall", profile_path(@profile, :anchor => "wall")
#=> <a href="/profiles/1#wall">Comment wall</a>

link_to "Ruby on Rails search", :controller => "searches", :query => "ruby on rails"
#=> <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>

link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux")
#=> <a href="/searches?foo=bar&amp;baz=quux">Nonsense search</a>
49
votes

If you want the quick and dirty way and don't worry about XSS attack, use params.merge to keep previous parameters. e.g.

<%= link_to 'Link', params.merge({:per_page => 20}) %>

see: https://stackoverflow.com/a/4174493/445908

Otherwise , check this answer: params.merge and cross site scripting

25
votes

If you want to keep existing params and not expose yourself to XSS attacks, be sure to clean the params hash, leaving only the params that your app can be sending:

# inline
<%= link_to 'Link', params.slice(:sort).merge(per_page: 20) %>

 

If you use it in multiple places, clean the params in the controller:

# your_controller.rb
@params = params.slice(:sort, :per_page)

# view
<%= link_to 'Link', @params.merge(per_page: 20) %>
6
votes

In case you want to pass in a block, say, for a glyphicon button, as in the following:

<%= link_to my_url, class: "stuff" do %>
  <i class="glyphicon glyphicon-inbox></i> Nice glyph-button
<% end %>

Then passing querystrings params could be accomplished through:

<%= link_to url_for(params.merge(my_params: "value")), class: "stuff" do %>
  <i class="glyphicon glyphicon-inbox></i> Nice glyph-button
<% end %>