Rodrigo Serrano
Rodrigo Serrano

Reputation: 1565

Why is Turbo not honoring link_to method: :post?

For a long time, Rails has provided a method: :post option in the link_to helper: when the option was given, Rails would intercept the click and issue a POST request, instead of the default GET request.

However, for some unknown reason, this is not working in Rails 7: despite adding method: :post to my link_to helper, Rails sends a GET request (not a POST request). I thought Turbo was supposed to take care of it, but it does not seem to be happening.

This is what you can do to reproduce, very simple steps:

$ rails new example_app
$ bin/rails g scaffold Book title
$ bin/rails db:create && bin/rails db:migrate
$ echo "<%= link_to "New book", new_book_path, method: :post %>" >> app/views/books/index.html.erb
$ bin/rails s

Now visit localhost:3000/books from your web browser, and click on the second "New book" link. I would expect getting an error (after all, I did not configure the proper POST route) but, unfortunately, Rails isues a GET request - and not a POST request, as it should have:

Started GET "/books/new" for ::1 at 2021-12-27 17:40:43 +0100
Processing by BooksController#new as HTML
  Rendering layout layouts/application.html.erb
  Rendering books/new.html.erb within layouts/application
  Rendered books/_form.html.erb (Duration: 9.1ms | Allocations: 5216)
  Rendered books/new.html.erb within layouts/application (Duration: 10.2ms | Allocations: 5594)
  Rendered layout layouts/application.html.erb (Duration: 12.9ms | Allocations: 7759)
Completed 200 OK in 25ms (Views: 13.6ms | ActiveRecord: 4.3ms | Allocations: 12404)

Why is this happening? Shouldn't Turbo intercept the link, and, as Rails UJS did in the past, send a POST request?

Upvotes: 13

Views: 9363

Answers (5)

ColoniusRex
ColoniusRex

Reputation: 31

Just in case anyone comes across this problem.. I was battling this for a while myself until something clicked. It seems some things are namespaced behind turbo_ when Turbo is enabled on Rails. I don't fully understand it yet but I do know this, so I figured I'd contribute my findings.

The following link_to does send a POST request.

    <%= link_to 'Click here', your_path(), data: { turbo_method: :post } %>

This will NOT work:

    <%= link_to 'Click here', your_path(), turbo_method: :post  %>

Upvotes: 0

Shreehari
Shreehari

Reputation: 359

Faced the same issue in ruby 3.04, rails 7. The post method was not honoured and was intercepted as an get request. Using a quick fix for now by changing link_to to an button.

<%= button_to "Logout", :logout, method: :post %>

Upvotes: 0

Cichol
Cichol

Reputation: 29

Rodrigo Serrano‘s answer works for POST. However, if turbo-method is set :delete, and redirect_to is used in the destroy action, after the 302 redirection, it will trigger the destroy action on the resource which is redirected to.

button_to does not have this problem.

I am using rails 7.0.1. There is an open issue https://github.com/hotwired/turbo-rails/issues/259 .

Upvotes: 0

Greg
Greg

Reputation: 6659

I faced a similar issue, but I fixed it differently than proposed here:

Pinned the @rails/ujs

$ bin/importmap pin @rails/ujs

and then in application.js added:

import Rails from "@rails/ujs"
Rails.start()

And link_to "...", "...", method: :delete started working for me.

Consider this solution when you have a legacy app with a bunch of method: links and you don't want to change them to turbo-method:

Upvotes: 6

Rodrigo Serrano
Rodrigo Serrano

Reputation: 1565

It seems to me that the Rails 7 docs have not been updated for Turbo and the missing UJS library. Even though the link_to documentation clearly states that link_to(..., ..., method: :post) should work, it clearly does not.

Diving into Turbo's documentation, there is a section called Performing Visits With a Different Method where it says to use link_to ..., ..., data: { 'turbo-method' => :post }, which DOES work.

Upvotes: 17

Related Questions