13

within my RoR project my delete method is not working. It's weird because it was working a day ago but now all it does it redirects me to the "friend" page. Another thing to note is that the pop up dialog of "are you sure?" also does not show up when deleting a friend when it was working previously. I read some solutions online stating to put "//= require jquery" and "//= require jquery_ujs" in your javascript file but all I could find was my manifest.js file in my "app/assets/config" directory.

Any help would be greatly appreciated.

index.html.erb

<% if user_signed_in? %>
  <table class="table table-striped table-bordered table-hover">
    <thead class="thead-dark">
      <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Phone</th>
        <th>Twitter</th>
        <th>User ID</th>
        <th></th>
      </tr>
    </thead>

    <tbody>
      <% @friends.each do |friend| %>
        <% if friend.user == current_user %>
          <tr>
            <td>
            <%= link_to friend.first_name + " " + friend.last_name, friend, style: 'text-decoration:none' %>
            </td>
            <td><%= friend.email %></td>
            <td><%= friend.phone %></td>
            <td><%= friend.twitter %></td>
            <td><%= friend.user_id %></td>
            <td>
              <%= link_to 'delete', 
              friend,
              :method => :delete,
              :confirm => "are you sure?", 
              class: "btn btn-danger btn-sm" %>
            </td>
          </tr>
        <% end %>
      <% end %>
      
    </tbody>
  </table>

  <br>

<% else %>
  <h1>Welcome to the Friend App</h1>
<% end %>

manifest.js

//= link_tree ../images
//= link_tree ../builds
//= require jquery
//= require jquery_ujs
Eyeslandic
  • 14,553
  • 13
  • 41
  • 54
Kyowan Kim
  • 377
  • 3
  • 12

9 Answers9

18

In Rails 7 the "old" way of specifying the delete method does not work. My guess is the change from rails-ujs to turbo is the culprit. Rails-ujs was moved into Rails as of version 5.1 and Hotwire Turbo replaces it in rails 7.

This is how I solved my problem:

route: destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy

.html.erb:

<%= link_to t('navigation.sign_out'), destroy_user_session_path, method: :delete, class: "btn btn-danger ml-3" %>

html: (notice the data-method="delete")

<a class="btn btn-danger ml-3" rel="nofollow" data-method="delete" href="/users/sign_out"><span class="translation_missing" title="translation missing: en.navigation.sign_out">Sign Out</span></a>

Error: No route matches [GET] "/users/sign_out"

Solved it with (solution source)

.html.erb:

<%= link_to t('navigation.sign_out'), destroy_user_session_path, data: { "turbo-method": :delete }, class: "btn btn-danger ml-3" %>

.html: (notice the data-turbo-method="delete")

<a data-turbo-method="delete" class="btn btn-danger ml-3" href="/users/sign_out"><span class="translation_missing" title="translation missing: en.navigation.sign_out">Sign Out</span></a>
JoelEsli
  • 451
  • 3
  • 8
  • Thank you! This did the trick for me. I was also wondering if there's any way to implement js.erb files into Ruby on Rails 7 with ESBuild and import maps? – Kyowan Kim Dec 31 '21 at 17:28
  • Can anyone explain what "t('navigation.signout')" does? Thank you. – Clint Laskowski Feb 28 '22 at 12:28
  • @ClintLaskowski: it fetches the right localized string for 'navigation.signout'. https://guides.rubyonrails.org/i18n.html – JoelEsli Mar 08 '22 at 06:15
  • So when we upgrade from older rails versions we have to replace every "method: :delete" with data: { "turbo-method": :delete }? I am unhappy about this. Now I have to replace so many things and I can't search and replace, because I already use the data field for different other things... – Metaphysiker Apr 16 '22 at 16:42
  • This change is documented in the official [Working with JavaScript in Rails](https://guides.rubyonrails.org/working_with_javascript_in_rails.html#replacements-for-rails-ujs-functionality) guide – bloudermilk Aug 03 '22 at 01:12
  • With turbo-method, it seems flash messages are not rendered, anyone knows a way to keep flash messages? – nico_lrx Dec 08 '22 at 07:50
13

Just a quick note for rails 7 if you want the confirmation message to work out of the box:

<%= link_to t('navigation.sign_out'),
  destroy_user_session_path,
  data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' },
  class: "btn btn-danger ml-3" %>
installero
  • 9,096
  • 3
  • 39
  • 43
6

Rails 7 uses Turbo and stimulus framework to increase frontend performance.

You need to install turbo and stimulus. Run below commands on your terminal:

$ rails importmap:install 
$ rails turbo:install stimulus:install

Make sure you are using turbo_method like:

<%= link_to "Sign Out", destroy_user_session_path, data: { turbo_method: :delete }, class: "nav-link" %>
Jai Chauhan
  • 4,035
  • 3
  • 36
  • 62
1

You need to go to section 7.5 of the https://guides.rubyonrails.org/getting_started.html. It explains why

we need to set the data-turbo-method and data-turbo-confirm HTML attributes of the "Destroy" link.

Read the entire section 7.5, including the destroy action in both examples. Also preserve log in your console and observe the errors when you click on Delete button. To avoid head slapping moments, in destroy action try to add status to redirect_to as per rails guides redirect_to whatever_path, status: :see_other this also applies to when you delete an object and render new, you need to set status :unprocessable_entity which leads to server response to 422.

the key here is to ensure you have turbo_method: :delete in your link_to for Turbo, then, method: :delete to change GET to delete, and finally your destroy action to have a status when you're using redirect_to in-order to avoid errors when/if browser redirects you to another location with DELETE method.

<%= link_to "Delete", friend, method: :delete, data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' }, class: 'btn btn-danger' %>
Elias Glyptis
  • 470
  • 5
  • 9
0

You can use button_to also instead of link_to

<%= button_to friend_path(friend), method: :delete do %>
  Delete
<% end %>
0

I upgraded my app to Rails 7 but didn't want to use import maps, turbo etc. so I came up with my own Javascript solution for adding a confirmation dialogue to my destroy links.

First of all I turned all my links into buttons which makes it a lot easier to trigger a delete request:

def link_to_destroy(object)
  path = send("#{controller_name.singularize}_url", object)
  button_to "Destroy", path, :method => :delete, :data => { :confirm => "Are you sure?" }, :form_class => "confirm_destroy", :class => "destroy_icon"
end

(Note that Rails will automatically wrap those buttons in a form tag with a delete method included. I found styling those buttons surprisingly easy. I had to change only one line of code in my CSS.)

This is the Javascript I am using to trigger the confirmation dialogue:

function ConfirmDestroy() {

  const forms = document.querySelectorAll('.confirm_destroy');

  forms.forEach(form => {
    form.addEventListener('submit', function(e) {
      handleSubmit(form, e);
    });
  });

  function handleSubmit(form, e) {
    e.preventDefault();
    let message = form.querySelector('button').dataset.confirm; // pull the actual confirmation message from the data-attribute 'confirm' to support multiple languages
    if (!confirm(message)) {
      return false;
    }
    form.submit();
  }

}

document.addEventListener('DOMContentLoaded', ConfirmDestroy);

I have tested it in the latest versions of Chrome, Safari and Firefox on Mac and haven't encountered any issues so far.


The good thing about this solution is that it also supports multiple languages. The actual confirmation message will simply get pulled from the confirm data attribute. So you can put there any string or message that you want.

Tintin81
  • 9,821
  • 20
  • 85
  • 178
0

For those who still having problems with this, here are some other steps that could help:

Rails version: 7.0.3.1

Reference: Rails 7: link_to method: :delete not working

follow next steps:

  • bundle add hotwire-rails
  • add gem importmap-rails
  • install importmap rails importmap:install
  • install hotwire rails hotwire:install

and next code works:

%td= link_to t('common.destroy'), task, data: { turbo_method: :delete, turbo_confirm: t('common.confirm') }

as additional info, using:

  • gem hamlit
  • gem simple_form
Vielinko
  • 1,659
  • 1
  • 13
  • 17
0

I was having the same problem and I am mystified. I tried everything but kept failing to destroy and the logs always showed the page rendering as HTML and not as turbo stream. I then switched to the Opera browser (from chrome) and everything worked as expected. make any sense?

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 04 '22 at 10:45
-1

You need to pass the path for the controller, not just the object.

<%= link_to 'delete', 
          friend_path(friend),
          :method => :delete,
          :confirm => "are you sure?", 
          class: "btn btn-danger btn-sm" %>

You also need to find the correct path for this request, you could do the following to find the matching routes for friend.

rails routes | grep friend