truongnm
truongnm

Reputation: 2474

Rails 6 - DESTROY path to GET although added rails/ujs

I'm using Rails 6, got this error again.

show.html.erb

<%= link_to "Delete", post_path(@post), class: "dropdown-item", method: :delete %>

controller and routes are set up without error.

app/javascript/packs/application.js

require("@rails/ujs").start();
// require("turbolinks").start();
require("@rails/activestorage").start();
require("channels");

When click on the link, I can see the log:

Started GET "/posts/19" for ::1 at 2019-09-04 23:50:30 +0900
Processing by PostsController#show as HTML
  Parameters: {"id"=>"19"}

Instead of DELETE.

This is what got rendered in HTML:

<a class="dropdown-item" rel="nofollow" data-method="delete" href="/posts/19">Delete</a>

In layouts I include application.js:

<%= javascript_pack_tag 'application' %>

In HTML:

<head>
  <meta name="csrf-param" content="authenticity_token">
  <meta name="csrf-token" content="+EskpcJWxzYlo5g5lOyRAnx7tgARKbeFqV21YgtRjnlT4/xsmWsRljfqbVmpSDSl2l0s9scz7+C2bezpiLy4fA==">


  <link rel="stylesheet" media="all" href="/assets/trix/dist/trix.self-6dd442511a4fc56685fca816ea1b42de7bbc8a0fd0bfd759530fa9e7625d1a6f.css?body=1" data-turbolinks-track="reload">
  <link rel="stylesheet" media="all" href="/assets/actiontext.self-a679dceacb4aa0b812495eb34e20291bc8eab82506add17d18f0b3b3d1353123.css?body=1" data-turbolinks-track="reload">
  <link rel="stylesheet" media="all" href="/assets/application.self-2115ce8ad5c8bf2c98589b69e9fc7c0d3ba5251b0d5ef251ec5b3da1da9cb7a8.css?body=1" data-turbolinks-track="reload">
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
  <script src="/packs/js/application-dffd55b262c09e354e1b.js"></script>
</head>

Actually change to button_to works, it generates this on HTML:

<form class="button_to" method="post" action="/posts/19">
  <input type="hidden" name="_method" value="delete">
  <input class="dropdown-item" type="submit" value="Delete">
  <input type="hidden" name="authenticity_token" value="ZnfQ05Ah/4LevuR8vXvcYN/CSNAoTDQuwpGHF4WrJDiVV8+wwb4ztsYdsKk9UPZ3k9Gxpfpd/gcobcSBEI6/6A==">
</form>

Notice this line: <input type="hidden" name="_method" value="delete">

I think the problem is Rails UJS hasn't been loaded. I open console and type Rails or Rails.handleMethod and I got

Uncaught ReferenceError: Rails is not defined
    at <anonymous>:1:1
(anonymous) @ VM9848:1

Upvotes: 3

Views: 2343

Answers (2)

Adrian Rama
Adrian Rama

Reputation: 53

Knowing

helper.link_to "delete", "/posts/19", :method => 'delete', class: 'dropdown-item'

Generates

<a class="dropdown-item" rel="nofollow" data-method="delete" href="/posts/19">Delete</a>

For me worked

button_to "Salir", "/posts/19", :method => 'delete', class: "dropdown-item"

Wich generate

<form class="button_to" method="post" action="/posts/19"><input type="hidden" name="_method" value="delete"><input class="dropdown-item" type="submit" value="delete"><input type="hidden" name="authenticity_token" value="UwJqclJbUaT0Y8Zl53-43JHG9Cc3_D3lOktsfB200jx8G0IFTF_yKhRgXSHXxlUssxtoTYcpt68FLjw-C0WL-g"></form>

I think it could be a solution approach.

Upvotes: 1

truongnm
truongnm

Reputation: 2474

I was able to solve the problem. I will share for you guys.

In my layout I have =javascript_pack_tag 'application' which load Rails UJS already.

In my view partial I also include another js script javascript_pack_tag 'posts/show'. The problems is in that script, I set to listen to click event then e.preventDefault(), turn out that Rails UJS can't create form delete, then GET request is sent.

document.addEventListener("DOMContentLoaded",function() {
  let postOption = document.getElementsById("post-options");
  postOption.addEventListener("click", function(e) {
      e.stopPropagation();
      this.classList.toggle("is-active");
    });
  });
});

Rails UJS

    // Handles "data-method" on links such as:
    // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
    handleMethod: function(link) {
      var href = rails.href(link),
        method = link.data('method'),
        target = link.attr('target'),
        csrfToken = rails.csrfToken(),
        csrfParam = rails.csrfParam(),
        form = $('<form method="post" action="' + href + '"></form>'),
        metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';

      if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) {
        metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
      }

      if (target) { form.attr('target', target); }

      form.hide().append(metadataInput).appendTo('body');
      form.submit();
    },

Upvotes: 1

Related Questions