105

I have a link that I need to submit a post request with. Normally, I'd use jQuery and prevent the link's default behavior and then submit a form to the destination. This seems like something Rails should be able to help me out with. Sure enough, the link_to method has an option for specifying a POST http method:

link_to "Profile", 'http://example.com/profile', method: :post

That works, but I need to add 2 parameters too. I tried:

link_to "Profile", 'http://example.com/profile', method: post, param1: 'value1', param2: 'value2'

That just added those parameters to the <a> HTML element, but didn't submit those when clicking the link:

<a rel="nofollow" param1="value1" param2="value2" data-method="post" href="http://example.com/profile">Profile</a>

Is there a way to do a POST request with parameters using link_to or any other Rails method? I'm using Rails 3.2.9.

at.
  • 50,922
  • 104
  • 292
  • 461
  • don't think you can do that. probably best doing it in your controller with net/http or HTTParty? – Mike Campbell Nov 16 '12 at 12:53
  • Can't do it in my controller, user needs to be directed to the other site. Looks like you're right though, there isn't a built-in link mechanism to do this for me. – at. Nov 16 '12 at 20:03

6 Answers6

162

The short answer is that if what you mean by "parameters" is form fields, then you simply can't do this (at least not in a straightforward way that I can see). You should instead use a form with a submit button, styled to look like a link (if that's what you want it to look like).

If on the other hand you had meant query parameters, then this would work:

link_to "Profile", profile_path(@profile.id, param1: 'value1', param2: 'value2'), method: :post
David Schmitt
  • 58,259
  • 26
  • 121
  • 165
Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82
  • 1
    Just updated my question, I'm actually using an external URL for these links. – at. Nov 16 '12 at 10:46
  • I've added a note basically saying that what you want to do is not possible using a link. You need a form with a submit button. – Chris Salzberg Nov 18 '12 at 07:41
  • 3
    It's important to note that if a user has javascript disabled the link will default to a "GET" request. – bkunzi01 Mar 07 '17 at 00:04
16

Note that if the user has JS disabled or you have removed the unobtrusive JS libraries that come by default, link_to will be silently submitted via a GET request.

In general, I am not very fond of having links that perform POST requests. I think that's the role of a form and a button.

Thus, an easy (and safer) alternative is to use the Rails button_to helper:

button_to 'Profile', profile_path(@profile, param1: 'value1', param2: 'value2')

button_to also supports the method option but as it defaults to post so I've just omitted it.

Kostas Rousis
  • 5,918
  • 1
  • 33
  • 38
8

You can encode parameters in the URL this way :

link_to "Profile", 'http://example.com/profile?' + {param1: 'value1', param2: 'value2'}.to_param, method: :post

If it does not fit your needs you are better use a form than a link_to.

Adrien Coquio
  • 4,870
  • 2
  • 24
  • 37
  • This is indeed a very nice way to add the parameters. – nathanvda Nov 16 '12 at 18:23
  • Doesn't work for my needs, the parameters need to be POST parameters. But thanks, I didn't know about the to_param method. You also need a `?` after profile. – at. Nov 16 '12 at 20:02
  • Ok I understand, then I think you have to write a form. You can write an helper method which will build this form if you need to repeat this logic several times. – Adrien Coquio Nov 16 '12 at 22:20
  • 1
    Notwithstanding that this doesn't answer the OP's question, you should use a url helper for this as in @shioyama's answer – Ben West Dec 15 '14 at 20:18
  • @BenWest : the helper was not initially used and I assumed it was meaningful (it may have been an external URL for example) – Adrien Coquio Dec 16 '14 at 00:08
8

For Rails 7 with Turbo

link_to "Profile", profile_path(@profile), data: { turbo_method: "post" }
Licke
  • 101
  • 1
  • 2
1

In order to POST data, you need a form. However, you don't need a submit button. If you want this to look like a link for some reason, you can actually make it a link that submits the form via JavaScript. In the example below, the POST resource is just a REST action that does not require any fields so there are no form input controls. If you wanted to post some data, just put hidden input fields in the form.

<%= form_tag('http://something_postable', :method => :post, :class => 'internal') %></form>
<%= link_to_function('Label for Link', 'previous("form").submit()', :title => 'Hover text for link') %>

The form is assigned a class so you can style it or hide it via CSS (e.g. 'display: inline')

Ammo Goettsch
  • 838
  • 8
  • 11
1

The parameters and the http method should be together {param1: 'value1', param2: 'value2', :method: :post}

<%= link_to "Profile", profile_path(@profile), {param1: 'value1', param2: 'value2', method: :post} %>
pangpang
  • 8,581
  • 11
  • 60
  • 96