236

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.

Jeff
  • 13,943
  • 11
  • 55
  • 103
craig
  • 25,664
  • 27
  • 119
  • 205
  • possible duplicate of [More-efficient way to pass the Rails params hash to named route](http://stackoverflow.com/questions/4559916/more-efficient-way-to-pass-the-rails-params-hash-to-named-route) – random Jan 19 '13 at 19:31
  • 1
    closely related: http://stackoverflow.com/questions/2124862/link-to-send-parameters-along-with-the-url-and-grab-them-on-target-page – Ciro Santilli OurBigBook.com Aug 14 '14 at 20:19

5 Answers5

375

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>
XeNoN
  • 694
  • 6
  • 16
Fred
  • 8,582
  • 1
  • 21
  • 27
  • 1
    Your answer helped me solve #1: <%= link_to "0", profiles_path(:bucket => '0', :sorting=>params[:sorting]) %>. Thanks. – craig Apr 23 '10 at 10:20
  • 1
    this is right. the new syntax is ` <%= link_to "Create Note", new_note_path(sender_id: @user.id) %>` – gsumk Sep 12 '19 at 22:09
49

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

Community
  • 1
  • 1
Siwei
  • 19,858
  • 7
  • 75
  • 95
  • 68
    Do not do this, it opens you up to xss attacks. – Daniel Nill Aug 27 '13 at 00:31
  • 2
    @DanielNill- Can you explain – Yarin Sep 08 '13 at 16:26
  • 3
    @Yarin There's a pretty good explanation at [this question](http://stackoverflow.com/questions/12271218/params-merge-and-cross-site-scripting). – James Oct 04 '13 at 20:01
  • 7
    @Yarin Arbitrarily printing parameters into the page which have been submitted by the user (and not necessarily cleaned) allows someone to link to your site with a link that encodes Javascript. That Javascript is then printed into the page and executes, potentially stealing cookies or doing nefarious tasks. Rails is normally pretty good at cleaning stuff that's printed into the page but it's better to be safe than sorry – Peter Nixey Oct 27 '13 at 12:54
25

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) %>
Greg Funtusov
  • 1,377
  • 15
  • 18
6

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 %>
zakelfassi
  • 2,936
  • 1
  • 22
  • 20
0

You can use the data- attribute as mentioned in the official rails guides like so:

  <%= link_to 'Link', link_path, data: { params: "per_page=20" } %>

params in the controller will then be:

{"per_page"=>"20" etc...

and this example can be accessed as params[:per_page]

DaveWoodall.com
  • 727
  • 6
  • 22