72

I am trying to get this link to work, performing a DELETE request:

<%= link_to "Sign Out", destroy_user_session_path, method: :delete %>

However when I click on it, my browser still performs a GET request (which fails for obvious reasons):

screenshot of browser network console

I have read on multiple other forum posts, that this might have something to do with jquery not being included. They mentioned you would need to un-comment a line in app/javascript/application.js, however mine is pretty empty:

// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"

These forum posts were also quite old, so I suspect something has changed in the meantime.

6
  • 12
    I have not used hotwired, but does changing method: :delete to data: { turbo_method: :delete } work? Commented Dec 24, 2021 at 16:49
  • 1
    Yes, this works for me, thanks :) there is only one weird thing: once the DELETE request was performed, my browser is redirected (as desired) but instead of doing a normal GET, it does another DELETE (in my case at "/"). The user doesn't notice it, it just shows up in the network console. Commented Dec 25, 2021 at 15:55
  • Check this github issue and specifically this comment Maybe the destroy_user_session_path and not specifying delete method fires a request twice... Commented Dec 25, 2021 at 16:05
  • 2
    @Nils - Try adding this status in your redirect: redirect_to action: 'some_action', status: 303. Because: If you are using XHR requests other than GET or POST and redirecting after the request then some browsers will follow the redirect using the original request method. This may lead to undesirable behavior such as a double DELETE. To work around this you can return a 303 See Other status code which will be followed using a GET request. Also see: api.rubyonrails.org/classes/ActionController/… Commented Apr 13, 2022 at 15:29
  • For some general clarification, see: turbo.hotwired.dev/handbook/… Commented Apr 13, 2022 at 15:41

5 Answers 5

79

As suggested here, the following will suffice:

<%= link_to "Sign Out", destroy_user_session_path, data: { "turbo-method": :delete } %>

I have tested this in my project and it seems to work fine. Thanks also to @alexts, you basically figured this out too, however the comment on GitHub even eliminated the double-request.

Sign up to request clarification or add additional context in comments.

8 Comments

I tried this a few days ago in my project and I could swear it was working. But now when I try this it does not work.
Could you post what versions of rails and devise you’re using?
button_to also creates a form.
Hey @Nils, just saw your comment. As I said, I tried this and it did work. Then for some reason it did not and frustrated I searched around and left my comment here. And then, a while later, it worked again. I do not know what I did wrong, what changed, but I was happy it did work and totally forgot about the comment I left.
@imarg : If your <form> (or another parent element such as a <div>) has data: { turbo: false } then you will also need to add turbo: true to your link_to, resulting in: <%= link_to "Sign Out", destroy_user_session_path, data: { turbo: true, turbo_method: :delete } %>
|
68

There are (at least) two ways to delete something in rails 7:

Using button_to (preferred IMHO):

<%= button_to 'Sign Out', destroy_user_session_path, method: :delete %>

Renders an HTML form which sends a POST request with a hidden _method attribute with 'delete' value. Rails will treat this as if it has a DELETE method (and route it to products#destroy or whatever your routes are saying). Do not use this one within another form (HTML forbids one form inside another).

Using link_to:

<%= link_to 'Sign Out', destroy_user_session_path, data: {turbo_method: :delete} %>

Renders a simple a tag with data-turbo-method attribute. This link sends a real DELETE request.

If your destroy action ends with a redirect_to, some browsers will redirect to a new location with DELETE method (causing errors), so make sure to add status: :see_other parameter to redirect_to, like the guides suggest.

Confirmation

If you want to add confirmation prompt to a button above:

<%= button_to 'Sign Out', destroy_user_session_path, method: :delete,
  form: {data: {turbo_confirm: 'Are you sure?'}} %>

If you want to add confirmation to a link above:

<%= link_to 'Sign Out', destroy_user_session_path,
  data: {turbo_method: :delete, turbo_confirm: 'Are you sure?'} %>

2 Comments

so if we use it inside form, should we use link_to instead button_to or is there any alternatives? ref: dev.to/paramagicdev/escaping-the-traditional-rails-form-4c4o
Note that button_to "text", [url], method: :delete uses DELETE, whereas button_to "text", [url], "data-turbo-method": :delete doesn't (no hidden _method input is added to the form). Found that out after replacing hundreds of link_to and button_to.
14

Found it on git

Run these commands

It worked for me.

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

4 Comments

Thanks, it was the missing lines for the rails tutorial to works. I've submitted a PR to improve the documentation with these lines !
This command will be reset import map with linked all javascript link. it's not working on rails 7.0.8
Also ran into issues with the Rails tutorial. These two commands solved it. <v7.1.3.2>
This solved it, I'm using ruby-3.3.1 and Rails 7.1.3.2. This is missing from the documentation guides.rubyonrails.org/getting_started.html#deleting-an-article
5

I had a more niche case where I'd turned off turbo globally in the rails 7 app like so:

// app/javascript/application.js
import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false

If you did that too, you might need to set turbo: true for the button_to approach to work.

Here's what worked for me:

<%= button_to 'Destroy', @page, method: :delete, form: 
  { data: { turbo: true, turbo_confirm: 'Are you sure?' } } %>

It's the same as other answers but it ensures turbo is indeed on for that element.

Notes

  • I didn't need ujs
  • I didn't need jquery or //= require jquery or anything like that.

Comments

-2

method: :delete just add a attribute

in order to make it useful, rails_ujs library is responsible try to include it that can be useful

1 Comment

He's using turbo rails and the Hotwire framework... that ujs library won't be necessary.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.