Skip to content


Subversion checkout URL

You can clone with
Download ZIP


button_to options are lost on GET request #2158

alexeymuranov opened this Issue · 20 comments

9 participants


If the button_to helper is used with :method => :get, the options parameters are appended to the action string and removed by the browser on submission.

Apparently it is a known behavior, how browsers treat forms submitted via GET. This does not happen if the method in POST.

It seems that when submitting via GET with button_to, the only way to pass options is to use hidden fields.


Can you provide a complete patch or at least a test case?.
Thank you.


Unfortunately i have no time to provide a patch now. Here are steps to reproduce the problem:

  • Create a new application:
$ rails new test_button
$ cd test_button
$ rails generate controller Button show
  • Add to show.html.erb:
<%= button_to 'GET test button', { :an_option => 'my_option' }, { :method => :get } %>
<%= button_to 'POST test button', { :an_option => 'my_option' }, { :method => :post } %>
<%= debug(params) %>
  • Edit routes.rb:
get "button/show"
post "button/show"
@exviva exviva referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.

I created a patch, but somebody please better tell me how I can split the options hash into standard keys that are used by the Routes module and into extra keys that are supposed to be request parameters, because what I've done just hurts my eyes :/.


You mean url_options from options? It seems they can usually be submitted in a single hash, i agree this is confusing.


@exviva if you mean your code:

options.except(:only_path, :protocol, :host, :subdomain, :domain, :tld_length, :port, :anchor, :trailing_slash, :controller, :action).each do |name, value|
  extra_params_tags += tag('input', :type => 'hidden', :name => name, :value => value)

than I think you don't need to call except function since options hash include only parameters after '?' in action (you could see it by adding 'puts "options - " + options.inspect' before 'url = options.is_a?(String) ? options : self.url_for(options)' line)

As to the root of this issue:

If the method is "get" and the action is an HTTP URI, the user agent takes the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type. The user agent then traverses the link to this URI. In this scenario, form data are restricted to ASCII codes.

Also here:

Hope, it'll help!


@alexeymuranov, @german my problem is that options may contain options for the Routes (like subdomain, action, controller, etc.) - which I don't want to end up as hidden inputs - and also other parameters, which should be used to build the hidden inputs (and not become query string parameters in the URL).

@german, I'll investigate your suggestion when I get home today.


@german, unfortunately I have to use except because otherwise the output contains stuff like:
<input type="hidden" name="action" value="show" />
<input type="hidden" name="controller value="users" />

That's why I need to extract from options only those keys, which are not used by the router.

@exviva exviva referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.

Hi again,

never mind about my previous doubts, I came up with a different approach: just change the query string params from the URL string into hidden inputs.


Thank you. Just a thought: wouldn't it be more consistent to always use hidden fields regardless of the submission method?


@alexeymuranov I can see a valid use case for separating query string parameters from post data in POST requests, so I guess we should play only with form[method=GET].


@exviva, i looked again at the patch you've created. I tried to use a similar approach --- first generating an url for options and then parsing it and storing values in hidden fields, but it was buggy with nested hashes. I ended up taking a solution from here, and it works fine:

I think that a real solution would be to implement a hidden_fields_for method analogous to url_for, based on Peter Marklund's code.


By the way, is there a rails function to list all params keys that should not be set explicitly in form fields, like :controller, :action, :_method, etc.?


@alexeymuranov I guess you're right about hidden_fields_for, but this is beyond the scope of button_to.

Regarding extracting "route" parameters from params, I couldn't find a way (see my original attempt).


Is this still an issue?


Added some options via the default_url_options method in ApplicationController. Can see the parameters appear in the form action, but as alex stated they get dropped off.


I think this is something to be handled in the application if it's required. I'm giving this a close as stale, please feel free to continue the discussion if you still think it's an issue, or start a new topic in the Rails core mailing list. Thanks!


I am facing the same problem. Trying to use "get" with button_to with an additional parameter, but the parameter is lost.


<%= button_to "Manage", admin_credentials_path(current_user, :context_user_id => params[:user_id]), method => :get %>


<form action="/users/11/admin/authenticate?context_user_id=10" class="button_to" method="get"><div><input type="submit" value="Manage" /></div></form>

But I actually never get the parameter context_user_id.

Whereas link_to works just fine.


I've made PR #9622 which i think, if accepted, might help to fix this.


How about making button_to accept a block so you can add hidden fields directly, e.g:

<%= button_to "Manage", admin_credentials_path(current_user), :method => :get do %>
<%= hidden_field_tag :context_user_id, params[:user_id] %>
<% end %>

That seems a cleaner solution than trying to mess with the url options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.