Destroy action
There are 2 alternatives to create an action button (or link) for :destroy:
-
create a mini form with
button_to, or -
use link_to with some special data attributes
button_to
- Pros
-
-
use POST instead of GET for proper redirection
-
simple to use
-
- Cons
-
-
Creates a small form, so don’t use it within another form
-
Confirmation
data-turbo-confirmneeds to go to the form, not to the button. -
Needs a little more CSS styling to be compatible with other bootstrap link buttons
-
button_to 'Destroy', @post,
method: :delete,
form: { 'data-turbo-confirm': 'Are you sure?' }
form.button_to {
display: inline-block;
}
link_to
- Pros
-
-
No separate form
-
mostly compatible with older
rails-ujsstyles
-
- Cons
-
-
Beware of the 303 trap (see below)
-
link_to 'Destroy', @post,
'data-turbo-method':
'data-turbo-confirm': 'Are you sure?'
The 303 trap of @hotwired/turbo
If you are sending a DELETE request via link_to … method: :delete, Rails
redirects with a 302 redirect, but Turbo needs a 303 to use GET after DESTROY.
Otherwise Turbo generates a new DELETE request. For example:
| First Request | Turbo answer | Result |
|---|---|---|
|
|
|
|
|
|
| For more informations, see https://github.com/hotwired/turbo/issues/84 |
As long Rails uses 302 instead of 302 here, you have to made a choice:
-
set the correct redirect code in each controller (yeah, don’t like it too)
-
Catch the response and change it for get requests (see below)
-
use
button_toinstead oflink_to
class ApplicationController < ActionController::Base
def redirect_to(url_options = {}, response_options = {})
response_options[:status] ||= :see_other unless request.get?
super url_options, response_options
end
end