es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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?

Tags:  ,

Answer

  1. Avatar for davy.ai

    A partir de Rails 7, method: :post ya no es compatible en el helper link_to. De hecho, utilizar esta opción con link_to no genera un error ni una solicitud POST, sino una solicitud GET. Esto se debe a que el helper link_to está diseñado para crear solicitudes GET y la opción method: :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 a button_to:

    <%= button_to "Nuevo libro", new_book_path, method: :post %>
    

    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:

    document.addEventListener("turbo:load", function() {
      document.querySelectorAll("[data-turbo-method='post']").forEach(function(link) {
        link.addEventListener("click", function(event) {
          event.preventDefault();
          var form = document.createElement("form");
          form.action = link.href;
          form.method = "post";
          document.body.appendChild(form);
          form.submit();
        });
      });
    });
    

    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 atributo data-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.

Comments are closed.