¿Por qué Turbo no respeta el método link_to: :post?
Durante mucho tiempo, Rails ha proporcionado la opción method: :post
en el ayudante link_to
: cuando se proporcionaba la opción, Rails interceptaba el clic y emitía una solicitud POST en lugar de la solicitud GET predeterminada.
Sin embargo, por alguna razón desconocida, esto no está funcionando en Rails 7: a pesar de agregar method: :post
a mi ayudante link_to
, Rails envía una solicitud GET en lugar de una solicitud POST. Pensé que Turbo se encargaría de esto, pero parece que no está sucediendo.
Esto es lo que puedes hacer para reproducirlo, pasos muy sencillos:
$ rails new example_app
$ bin/rails g scaffold Book title
$ bin/rails db:create && bin/rails db:migrate
$ echo "<%= link_to "Nuevo libro", new_book_path, method: :post %>" >> app/views/books/index.html.erb
$ bin/rails s
Ahora visita localhost:3000/books
desde tu navegador web y haz clic en el segundo enlace “Nuevo libro”. Esperaría recibir un error (después de todo, no configuré la ruta POST adecuada), pero desafortunadamente, Rails emite una solicitud GET en lugar de una solicitud POST, como debería:
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)
¿Por qué está sucediendo esto? ¿No debería Turbo interceptar el enlace y, como hacía Rails UJS en el pasado, enviar una solicitud POST?
davy.ai
A partir de Rails 7,
method: :post
ya no es compatible en el helperlink_to
. De hecho, utilizar esta opción conlink_to
no genera un error ni una solicitud POST, sino una solicitud GET. Esto se debe a que el helperlink_to
está diseñado para crear solicitudes GET y la opciónmethod: :post
no anula este comportamiento.En su lugar, debes usar el helper
button_to
para crear un formulario que envíe una solicitud POST. Esto se puede hacer pasando la ruta y cualquier opción adicional como argumentos abutton_to
:Además, debido a que Turbo actualmente no admite la interceptación de enlaces con
method: :post
, deberás agregar un poco de JavaScript para enviar manualmente el formulario usando Turbo:Este código escucha el evento
turbo:load
(que se dispara después de un cambio de página en una aplicación habilitada para Turbo), encuentra todos los enlaces con el atributodata-turbo-method
establecido en"post"
, y agrega un event listener que evita el comportamiento predeterminado al hacer clic, crea un formulario, establece sus atributos action y method en la href del enlace y “post”, respectivamente, añade el formulario al cuerpo del documento y lo envía.Con estos cambios, al hacer clic en el botón “Nuevo libro” se enviará una solicitud POST al servidor, como se espera.