Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rails 7 data-confirm not working for User deletion #5448

Closed
odinsride opened this issue Jan 5, 2022 · 24 comments · Fixed by #5548
Closed

Rails 7 data-confirm not working for User deletion #5448

odinsride opened this issue Jan 5, 2022 · 24 comments · Fixed by #5548

Comments

@odinsride
Copy link

odinsride commented Jan 5, 2022

Environment

  • Ruby 3.0.3p157
  • Rails 7.0.0
  • Devise 4.8.1

Current behavior

When clicking the default "Cancel my account" link, the data-confirm is not triggering, and instead it is deleting the user account right away. I am using Rails 7 with turbo / stimulus / importmap, although I have data-turbo set to false for my edit user form. Here is the form code:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, 'data-turbo': false }) do |f| %>
  <%= render DeviseErrorsComponent.new(resource: resource) %>

  <div class="md:flex md:space-x-4">
    <div class="flex-1">
      <div class="o-control-group">
        <%= f.label :first_name, class: "o-label" %>
        <%= f.text_field :first_name, autofocus: true, autocomplete: 'disabled', class: "o-input" %>
      </div>
    </div>

    <div class="flex-1">
      <div class="o-control-group">
        <%= f.label :last_name, class: "o-label" %>
        <%= f.text_field :last_name, autocomplete: 'disabled', class: "o-input" %>
      </div>
    </div>
  </div>

  <div class="o-control-group">
    <%= f.label :timezone, class: "o-label" %>
    <%= f.time_zone_select :timezone, ActiveSupport::TimeZone.us_zones, { default: "Eastern Time (US & Canada)" }, { class: "o-input" } %>
  </div>
  
  <div class="o-control-group">
    <%= f.label :email, class: "o-label" %>
    <%= f.email_field :email, placeholder: "john@gmail.com", autocomplete: "email", class: "o-input" %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="o-control-group">
    <%= f.label :current_password, class: "o-label" %>
    <%= f.password_field :current_password, autocomplete: "current-password", placeholder: "●●●●●●●●", class: "o-input" %>
    <div class="ml-2 mt-2 text-sm font-semibold text-gray-400">Your current password is required to confirm your changes</div>
  </div>

  <div class="text-center">
    <%= f.submit "Update", class: "o-btn o-btn--primary w-1/3" %>
    <div class="mt-4 text-sm text-gray-400">Unhappy? <%= button_to "Close account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete , class: "o-link o-link--primary" %></div>
  </div>
<% end %>

The data: { confirm: "Are you sure?" } bit does not seem to be doing anything in my setup.

Expected behavior

Clicking the "Cancel my account" link prompts the user to confirm before their account is deleted.

@nejdetkadir
Copy link

https://twitter.com/excid3/status/1471241559085617154

@spaquet
Copy link

spaquet commented Jan 12, 2022

Can you try this

<%= button_to "Delete my account", registration_path(resource_name), form: { data: { turbo_confirm: "Are you sure?" } }, method: :delete %>

@mdorr
Copy link

mdorr commented Jan 14, 2022

Can you try this

<%= button_to "Delete my account", registration_path(resource_name), form: { data: { turbo_confirm: "Are you sure?" } }, method: :delete %>

Having a similar issue on Rails 7.0.0. Can confirm that form: { data: { turbo_confirm: 'message' }} works as expected. (Or, if using link_to, just data: { turbo_confirm: 'message' }). Thanks for the hint @nejdetkadir & @spaquet !

@tokyodaruma
Copy link

Also as a side-note, the config/routes.rb will need to handle the redirect following the deletion of the user. I found this write-up to be helpful 👍🏻

@Gustavovaldezurango
Copy link

ami no me funciona y estoy trabajando con esa version de rails 7 los men sajes de confirmacion

<%= link_to "Salir", destroy_user_session_path, form: { data: { turbo_confirm: "Are you sure?" } },:method => :delete, class: "salir"%>

@TadesseDev
Copy link

None of the above is working for me. and I am using rails 7.0.4

@MohamedMedhat21
Copy link

MohamedMedhat21 commented Sep 27, 2022

nothing worked with me
ruby 3.1.2
Rails 7.0.4

The browser keeps refreshing and does nothing

<%= link_to 'Delete', @friend, data: {turbo_method: :delete, turbo_confirm: 'Sure?'}, class: "btn btn-danger" %>

also with this

<%= link_to 'Delete', @friend, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %>

@wangekko
Copy link

wangekko commented Oct 11, 2022

ruby 3.1.0
rails 7.0.3
also not work, need upgrade rails version?

<%= button_to "Refund", refunds_path, remote: true, params: { id: Id}, 
                     form: { data: { turbo_confirm: "Are you sure?" } }, class: 'btn btn-danger btn-xs del-btn'  %>

@psantos10
Copy link

psantos10 commented Oct 23, 2022

ruby 3.1.0 rails 7.0.3 also not work, need upgrade rails version?

<%= button_to "Refund", refunds_path, remote: true, params: { id: Id}, 
                     form: { data: { turbo_confirm: "Are you sure?" } }, class: 'btn btn-danger btn-xs del-btn'  %>

Try this:

<%= button_to "Refund", refunds_path(@refund), data: { "turbo-confirm": "Are you sure?" } }, class: 'btn btn-danger btn-xs del-btn' %>

@sumantind
Copy link

sumantind commented Nov 18, 2022

ruby 3.1.2
Rails 7.0.4
This work for me
<%= button_to "Destroy", friend, method: :delete, data: {"turbo-confirm": 'Are you sure?'} %>

@alexbevi
Copy link

Stumbled upon this while trying to fix a similar issue. https://stackoverflow.com/a/70482989/195509 solved it for me with:

<%= link_to 'Delete', your_path_here, data: { "turbo-method": :delete, "turbo-confirm": 'Are you sure?' } %>

carlosantoniodasilva added a commit that referenced this issue Jan 31, 2023
Treat `:turbo_stream` request format as a navigational format, much like
HTML, so Devise/responders can work properly.

Allow configuring the `error_status` and `redirect_status` using the
latest responders features, via a new custom Devise responder, so we can
customize the both responses to match Hotwire/Turbo behavior, for
example with `422 Unprocessable Entity` and `303 See Other`,
respectively. The defaults aren't changing in Devise itself (yet), so it
still responds on errors cases with `200 OK`, and redirects on non-GET
requests with `302 Found`, but new apps are generated with the new
statuses and existing apps can opt-in. Please note that these defaults
might change in a future release of Devise.

PRs/Issues references:

#5545
#5529
#5516
#5499
#5487
#5467
#5440
#5410
#5340

#5542
#5530
#5519
#5513
#5478
#5468
#5463
#5458
#5448
#5446
#5439
carlosantoniodasilva added a commit that referenced this issue Jan 31, 2023
Treat `:turbo_stream` request format as a navigational format, much like
HTML, so Devise/responders can work properly.

Allow configuring the `error_status` and `redirect_status` using the
latest responders features, via a new custom Devise responder, so we can
customize the both responses to match Hotwire/Turbo behavior, for
example with `422 Unprocessable Entity` and `303 See Other`,
respectively. The defaults aren't changing in Devise itself (yet), so it
still responds on errors cases with `200 OK`, and redirects on non-GET
requests with `302 Found`, but new apps are generated with the new
statuses and existing apps can opt-in. Please note that these defaults
might change in a future release of Devise.

PRs/Issues references:

#5545
#5529
#5516
#5499
#5487
#5467
#5440
#5410
#5340

#5542
#5530
#5519
#5513
#5478
#5468
#5463
#5458
#5448
#5446
#5439
carlosantoniodasilva added a commit that referenced this issue Jan 31, 2023
Treat `:turbo_stream` request format as a navigational format, much like
HTML, so Devise/responders can work properly.

Allow configuring the `error_status` and `redirect_status` using the
latest responders features, via a new custom Devise responder, so we can
customize the both responses to match Hotwire/Turbo behavior, for
example with `422 Unprocessable Entity` and `303 See Other`,
respectively. The defaults aren't changing in Devise itself (yet), so it
still responds on errors cases with `200 OK`, and redirects on non-GET
requests with `302 Found`, but new apps are generated with the new
statuses and existing apps can opt-in. Please note that these defaults
might change in a future release of Devise.

PRs/Issues references:

#5545
#5529
#5516
#5499
#5487
#5467
#5440
#5410
#5340

#5542
#5530
#5519
#5513
#5478
#5468
#5463
#5458
#5448
#5446
#5439
carlosantoniodasilva added a commit that referenced this issue Jan 31, 2023
Treat `:turbo_stream` request format as a navigational format, much like
HTML, so Devise/responders can work properly.

Allow configuring the `error_status` and `redirect_status` using the
latest responders features, via a new custom Devise responder, so we can
customize the both responses to match Hotwire/Turbo behavior, for
example with `422 Unprocessable Entity` and `303 See Other`,
respectively. The defaults aren't changing in Devise itself (yet), so it
still responds on errors cases with `200 OK`, and redirects on non-GET
requests with `302 Found`, but new apps are generated with the new
statuses and existing apps can opt-in. Please note that these defaults
might change in a future release of Devise.

PRs/Issues references:

#5545
#5529
#5516
#5499
#5487
#5467
#5440
#5410
#5340

#5542
#5530
#5519
#5513
#5478
#5468
#5463
#5458
#5448
#5446
#5439
@carlosantoniodasilva
Copy link
Member

The main branch should contain all that's necessary for fully working with Turbo now, which should fix this. A new version will be released soon, but feel free to test it out from the main branch in the meantime, and report back on any issues. Thanks.

@Hombre2014
Copy link

My setup is like this:
ruby 3.1.1p18
rails 7.0.4.2
devise 4.9.0
responders 3.1.0

I have this code in my form:

<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
    <% if @minimum_password_length %>
      <br />
      <em><%= @minimum_password_length %> characters minimum</em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "current-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

<h3>Cancel my account</h3>

<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?", turbo_method: :delete }, method: :delete %></p>


<%= link_to "Back", :back %>

and it is working but if I changed it to button_to accordingly:

<%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %>

it does not and deletes the resource without warning.

@carlosantoniodasilva
Copy link
Member

@Hombre2014 which version of turbo and turbo-rails are you using?

See this note from the wiki:

Note: turbo-rails v1.3.0+ should be used for data: { turbo_confirm: "" } compatibility in buttons, prior to that you should use form: { data: { turbo_confirm: "" } } so that the option gets set on the form wrapping the button. (it includes Turbo 7.2.0, which contains this fix for that behavior.)

With button_to and previous versions of turbo / turbo-rails, you might need to pass the data turbo_confirm to the form, i.e. use form: { data: { turbo_confirm: "..." } } as shown above to get the confirmation to work.

@Hombre2014
Copy link

Hi @carlosantoniodasilva ,

Yes, I saw this. I am using turbo-rails 1.3.3.

@carlosantoniodasilva
Copy link
Member

@Hombre2014 Not sure that that could be then... is that the only button not working with confirmation? That's basically Turbo behavior so it should be nothing Devise specific.

In my test app I have that exact same code:

<%= button_to "Cancel my account", registration_path(resource_name), 
  data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %>

And it works fine:

CleanShot.2023-02-24.at.13.18.47.mp4

Even if I remove the "confirm" and leave only "turbo_confirm", the HTML I get is this and it works:

<button data-turbo-confirm="Are you sure?" type="submit">Cancel my account</button>

Also using turbo-rails 1.3.3:

% bundle info turbo
  * turbo-rails (1.3.3)
	Summary: The speed of a single-page web application without having to write any JavaScript.
	Homepage: https://github.com/hotwired/turbo-rails

Sorry I can't be of more help there, confirmation is a Turbo feature and nothing Devise interferes with.

@Hombre2014
Copy link

OK, @carlosantoniodasilva I just try it with the code provided:

I added the button_to option as well:

<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?", turbo_method: :delete }, method: :delete %></p><br>
<p>Try this <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></p>

Now if I click the button_to it does delete it immediately without the alert.
So, my point is that link_to is working correctly, but button_to does not.

@carlosantoniodasilva
Copy link
Member

@Hombre2014 I pasted your code into my sample app and it worked:

CleanShot.2023-02-24.at.13.46.54.mp4

Can you get that confirmation to work on any other button in your app, that's not a devise related one? Like I mentioned, this doesn't seem to be an issue with Devise, but with the confirmation feature provided by Turbo, and something your app, not playing nicely.

Just in case, I'd try the form: { data: {} } thing too.

@lapser
Copy link

lapser commented Mar 7, 2023

I get the same behavior as @odinsride, @Hombre2014 and many others here: when the default "Cancel my account" link/button is clicked then the user account is deleted right away.

I tried:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  ...
<% end %>

<h3>Cancel my account</h3>


These, without triggering any alert, do DELETE "/users" and do delete the user.<br>
1. <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %><br>
2. <%= button_to "Delete my account", registration_path(resource_name), form: { data: { turbo_confirm: "Are you sure?" } }, method: :delete %><br><br>

These, without triggering any alert, do POST "/users" and don't delete the user.<br>
3. <%= button_to "Refund", registration_path(resource_name), data: { "turbo-confirm": "Are you sure?" }, class: 'btn btn-danger btn-xs del-btn'  %><br>
4. <%= button_to 'Delete', registration_path(resource_name), data: { "turbo-method": :delete, "turbo-confirm": 'Are you sure?' } %><br><br>

This, without triggering any alert, does GET "/users" and doesn't delete the user.<br>
5. <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?", turbo_method: :delete }, method: :delete %><br><br>

Using ruby 2.7.2p137, rails 7.0.4.2, devise 4.9.0

$ bundle list
  * actioncable (7.0.4.2)
  * actionmailbox (7.0.4.2)
  * actionmailer (7.0.4.2)
  * actionpack (7.0.4.2)
  * actiontext (7.0.4.2)
  * actionview (7.0.4.2)
  * activejob (7.0.4.2)
  * activemodel (7.0.4.2)
  * activerecord (7.0.4.2)
  * activestorage (7.0.4.2)
  * activesupport (7.0.4.2)
  * addressable (2.8.1)
  * autoprefixer-rails (10.4.13.0)
  * bcrypt (3.1.18)
  * bindex (0.8.1)
  * bootsnap (1.16.0)
  * bootstrap (5.2.3)
  * builder (3.2.4)
  * capybara (3.38.0)
  * concurrent-ruby (1.2.2)
  * crass (1.0.6)
  * date (3.3.3)
  * debug (1.7.1)
  * devise (4.9.0)
  * erubi (1.12.0)
  * execjs (2.8.1)
  * ffi (1.15.5)
  * globalid (1.1.0)
  * i18n (1.12.0)
  * importmap-rails (1.1.5)
  * io-console (0.6.0)
  * irb (1.6.2)
  * jbuilder (2.11.5)
  * loofah (2.19.1)
  * mail (2.8.1)
  * marcel (1.0.2)
  * matrix (0.4.2)
  * method_source (1.0.0)
  * mini_mime (1.1.2)
  * minitest (5.18.0)
  * msgpack (1.6.1)
  * mysql2 (0.5.5)
  * net-imap (0.3.4)
  * net-pop (0.1.2)
  * net-protocol (0.2.1)
  * net-smtp (0.3.3)
  * nio4r (2.5.8)
  * nokogiri (1.14.2)
  * orm_adapter (0.5.0)
  * popper_js (2.11.6)
  * public_suffix (5.0.1)
  * puma (5.6.5)
  * racc (1.6.2)
  * rack (2.2.6.3)
  * rack-test (2.0.2)
  * rails (7.0.4.2)
  * rails-dom-testing (2.0.3)
  * rails-html-sanitizer (1.5.0)
  * railties (7.0.4.2)
  * rake (13.0.6)
  * regexp_parser (2.7.0)
  * reline (0.3.2)
  * responders (3.1.0)
  * rexml (3.2.5)
  * rubyzip (2.3.2)
  * sassc (2.4.0)
  * sassc-rails (2.1.2)
  * selenium-webdriver (4.8.1)
  * sprockets (4.2.0)
  * sprockets-rails (3.4.2)
  * stimulus-rails (1.2.1)
  * thor (1.2.1)
  * tilt (2.1.0)
  * timeout (0.3.2)
  * turbo-rails (1.4.0)
  * tzinfo (2.0.6)
  * warden (1.2.9)
  * web-console (4.2.0)
  * webdrivers (5.2.0)
  * websocket (1.2.9)
  * websocket-driver (0.7.5)
  * websocket-extensions (0.1.5)
  * xpath (3.2.0)
  * zeitwerk (2.6.7)

Tested in Firefox and Chrome.

P.S.: IMHO Adding in Devise an option to send a confirmation email to the user in order to delete his/her account would be better.

@lapser
Copy link

lapser commented Mar 7, 2023

The problem seems to be gone! I just removed the following statements from the file /rails-app/app/javascript/application.js (I'm using importmap and already pinned the libraries in file /rails-app/config/importmap.rb):

import "popper"
import "bootstrap"

However, IMHO adding in Devise an option to send a confirmation email to the user in order to delete his/her account would be good.

@kwtuku
Copy link

kwtuku commented Mar 7, 2023

Hi @Hombre2014, @lapser

I think it may be that the version of @hotwired/turbo is not higher than 7.2.0.

If you use jsbundling-rails, I want to know package.json and yarn list | grep turbo.

If you use importmap-rails, I want to know config/importmap.rb and <script type="importmap"> in devtools elements and node_modules/turbo.es2017-esm.js in devtools sources like below.

<script type="importmap">
image

node_modules/turbo.es2017-esm.js
image

@carlosantoniodasilva
Copy link
Member

Based on the listed gem versions, it's using turbo-rails 1.4 which should have the latest Turbo I believe.

That said, it does appear to be something with Turbo as the behavior to show a confirmation message and/or send a DELETE request is all Turbo behavior, nothing specific to Devise there. @lapser are you able to use confirm and/or method with other buttons / links that aren't Devise? Is Turbo navigation working fine across the app? I'd start there.

P.S.: IMHO Adding in Devise an option to send a confirmation email to the user in order to delete his/her account would be better.

The confirmation is just a simple way to avoid a button click from triggering the Delete provided by Devise, you're able to change that behavior in your app if necessary. For example we added a password confirmation step.

In any case, I'm going to consider this as a possible feature for the future. Thanks!

@jaimealves17
Copy link

@FernandoMafra
Copy link

This works for me:

<%= link_to "Delete", coin, data: { turbo_confirm: "Are you sure?", turbo_method: :delete } %> where registration_path(resource_name) <=> coin (in my code)

The error occurs because GEMFILE is using Hotwire Turbo Streams.

Your "error" is associated with data: { confirm: "Are you sure?" }, which is fine for the default behavior WITHOUT Turbo Streams, that belongs to hotwire library. So the difference is related to the choice of approach and LIBRARY you are using in your application.

If you are using Turbo Streams, the correct approach is the one above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.