Query parameters with url_for?

24,005

Solution 1

Use named routes.

edit_post_path(@post, :qp => "asdf")

Solution 2

You can use polymorphic_path

polymorphic_path([:edit, @post], :qp => 'asdf')

Solution 3

You can pass params to url_for. Checkout it in the sourcecode: https://github.com/rails/rails/blob/d891c19066bba3a614a27a92d55968174738e755/actionpack/lib/action_dispatch/routing/route_set.rb#L675

Solution 4

The answer from Simone Carletti indeed works, but there are times when one wants to construct the URL using objects as described in the Rails routing guide, and not rely on the _path helpers.

The answers from both Ben and Swards are attempting to describe exactly how to do this, but for me the syntax used results in an error (using Rails 4.2.2, which has the same behaviour as 4.2.4, which is the current stable release as of this answer).

The correct syntax for creating a URL/path from objects while also passing parameters should be, as opposed to a nested array, rather a flat array containing the URL components, plus a hash as the final element:

url_for([:edit, @post, my_parameter: "parameter_value"])

Here the first two elements are parsed as the components for the URL, and the hash is considered as parameter(s) for the URL.

This also works with link_to:

link_to( "Link Text", [:edit, @post, my_parameter: "parameter_value"])

When I call url_for as suggested by Ben & Swards:

url_for([[:edit, @post], my_parameter: "parameter_value"])

I get the following error:

ActionView::Template::Error (undefined method 'to_model' for #<Array:0x007f5151f87240>)

The trace shows that this is being called from polymorphic_routes.rb in ActionDispatch::Routing, via url_for from routing_url_for.rb (ActionView::RoutingUrlFor):

gems/actionpack-4.2.2/lib/action_dispatch/routing/polymorphic_routes.rb:297:in `handle_list'
gems/actionpack-4.2.2/lib/action_dispatch/routing/polymorphic_routes.rb:206:in `polymorphic_method'
gems/actionpack-4.2.2/lib/action_dispatch/routing/polymorphic_routes.rb:134:in `polymorphic_path'
gems/actionview-4.2.2/lib/action_view/routing_url_for.rb:99:in `url_for'

The problem being, that it's expecting an array of URL components (eg. symbols, model objects, etc), not an array containing another array.

Looking at the appropriate code from routing_url_for.rb, we can see that when it receives an array which has a hash as the final element, it will then extract the hash and treat as parameters, leaving then just the array with the URL components.

Which is why the flat array with a hash as the last element works, and the nested array does not.

Share:
24,005
randomguy
Author by

randomguy

Living to learn. Learning to live.

Updated on October 31, 2020

Comments

  • randomguy
    randomguy over 3 years
    url_for([:edit, @post])
    

    is working and generating /comments/123/edit. Now I need to add a query parameter, so that instead of

    /comments/123/edit
    

    it is

    /comments/123/edit?qp=asdf
    

    I tried url_for([:edit, @post], :qp => "asdf") but no go.

  • shredding
    shredding over 10 years
    How can i create an absolute path like that?
  • Simone Carletti
    Simone Carletti over 10 years
    Use the _url instead of _path: edit_post_url(@post, :qp => "asdf")
  • Brad
    Brad over 6 years
    This is not made clear in the api docs. Thank you so much, more upvotes needed.
  • Dorian
    Dorian over 2 years
    still not sure how I would do polymorphic_url(event, locale: :fr) for instance, I get /Users/dorianmariefr/.rvm/gems/ruby-3.0.3/gems/actionpack-6.‌​1.4.3/lib/action_dis‌​patch/routing/route_‌​set.rb:515:in url_for': wrong number of arguments (given 2, expected 1) (ArgumentError)` with url_for