devise
devise copied to clipboard
Devise 4.8.1 + Rails 7.0.0 | Undefined method 'user_url'
Pre-check
- Created a new rails-app with
rails new app-name -a propshaft -j importmap -c tailwind
- Added
gem 'devise', '~> 4.8', '>= 4.8.1'
toGemfile
and followed installation instructions
Environment
- Ruby 3.0.3p157
- Rails 7.0.0
- Devise 4.8.1
Current behavior
- Receiving
NoMethodError (undefined method 'user_url' for #<Devise::RegistrationsController:0x0000000000d638>)
upon successful user registration. - User gets persisted in database
Demo app to reproduce the error is available here
Expected behavior
- Redirect to
root_path
without error
Ran into this at the same time as you 😆
Quick fix, tl;dr
Add :turbo_stream
as a navigational format. This line goes in config/initializers/devise.rb
. I haven't tested this extensively, but I think it should be fine.
config.navigational_formats = ['*/*', :html, :turbo_stream]
More detail
A few lines from a trace starting with the offending line in registrations controller: https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/app/controllers/devise/registrations_controller.rb#L25
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/app/controllers/devise/registrations_controller.rb#L111-L113
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/lib/devise/controllers/helpers.rb#L264-L266
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/lib/devise.rb#L218-L220
Basically, requests in Rails 7 may come with format :turbo_stream
rather than simply :html
. This causes is_navigational_format?
to be falsey and thus after_sign_up_path_for
returns nil
. With location: nil
for responds_with
, the redirect path resolves from the resource - in our case the user.
I'm happy to open a PR for this, though someone with more familiarity with turbo should sanity check it.
@erik-brueggemann my understanding is that method: :delete won't work with a link_to when not using UJS (which is not a dependency by default in Rails 7). So the sign_out method is going to be called as a GET, which is the fallback, resulting in an error.
You can try changing link_to to button_to (which I don't like), or add data-turbo-method="delete", like so:
<%= link_to "Log out", destroy_user_session_path,
data: {
"turbo-method": :delete
}, class: "link-secondary smooth" %>
A problem I am trying to find a solution for with this approach is that upon singing out it won't redirect to the root, but to the page the user was on before signing out, which, of course, most probably requires authorisation, so it is not the best experience.
The approach above works without the @nickrivadeneira fix (however, you might be experiencing a different issue). I'm not sure what is it changes exactly in the behaviour. I was hoping it will be a fix for my issue, but it isn't... any help will be appreciated.
Hi @nortonandreev, the problem you're describing is yet another one that resulted from the Rails 7 / turbo-rails aftermath as far as I can tell.
This particular issue here wasn't meant to address the log out mechanism, but rather user registration only. For that, the fix suggested by @nickrivadeneira makes sense to me - nevertheless you've got a point! It's probably a good idea to open a separate issue to find a permanent solution for that?
But since we've already brought it up, instead of changing from link_to
to button_to
and instead of adding the :delete
data-tag, you might try editing your config/devise.rb
to sign out via GET
instead of DELETE
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :get # <= change this from :delete to :get and remove the `method:` in your `link_to` helper
Happy to open up another issue if ya'll think it's two separate topics.
But since we've already brought it up, instead of changing from
link_to
tobutton_to
and instead of adding the:delete
data-tag, you might try editing yourconfig/devise.rb
to sign out viaGET
instead ofDELETE
just curious - wouldn't that open one up to csrf attacks?
Hi @nortonandreev, the problem you're describing is yet another one that resulted from the Rails 7 / turbo-rails aftermath as far as I can tell.
This particular issue here wasn't meant to address the log out mechanism, but rather user registration only. For that, the fix suggested by @nickrivadeneira makes sense to me - nevertheless you've got a point! It's probably a good idea to open a separate issue to find a permanent solution for that?
But since we've already brought it up, instead of changing from
link_to
tobutton_to
and instead of adding the:delete
data-tag, you might try editing yourconfig/devise.rb
to sign out viaGET
instead ofDELETE
# The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = :get # <= change this from :delete to :get and remove the `method:` in your `link_to` helper
Happy to open up another issue if ya'll think it's two separate topics.
The changelog says that "Please note that Turbo integration is not fully supported by Devise yet.". It would be nice if someone familiar with the matter updates us on what does this mean exactly and if there is some ETA of when full support will be added. I don't really want to waste hours implementing hacky solutions which might make my app vulnerable. On the other hand, I don't want to be waiting forever, if devise won't be fully updated to support Rails 7.
method: :delete in my link_to dont working, only work this format >
<%= link_to "Deletar", admin_admin_path(admin), data: { "turbo-method": :delete, confirm: "Certeza que deseja excluir essa conta?" }, class: "btn btn-danger btn-sm" %>
For now you have to disable turbo on devise links, i.e. data: { turbo: false }
. I should have some time to look into more official turbo integration soon.
For now you have to disable turbo on devise links, i.e.
data: { turbo: false }
. I should have some time to look into more official turbo integration soon.
all right, thanks.
As noted by @nortonandreev this worked for me in an app with Rails 7 and importmap
<%= link_to "Log out", destroy_user_session_path,
data: {
"turbo-method": :delete
} %>
https://github.com/heartcombo/devise/issues/5439#issuecomment-997292547
This solved my issue to help me close out the initial setup of my new application that I'm working on, thank you!
The suggestion by @nortonandreev works for me, but adds an additional, failing and unnecessary (DELETE) HTTP request:
Started DELETE "/users/sign_out" for 127.0.0.1 at 2022-03-03 17:33:09 +0100
Processing by Users::SessionsController#destroy as TURBO_STREAM
[...]
Redirected to http://localhost:3000/
Completed 302 Found in 5ms (ActiveRecord: 0.3ms | Allocations: 3175)
Started DELETE "/" for 127.0.0.1 at 2022-03-03 17:33:10 +0100
ActionController::RoutingError (No route matches [DELETE] "/")
I added , data: { turbo: false }
to all link_to
and form_for
helpers on the Devise views.
I am on Rails 7.0.2.3 and I didn't have this issue. Maybe upgrading to this version of rails or higher might fix it,
im having this same problem in a app with bootstrap, link_to perfoms GET method instead DELETE even if i use data: {turbo_method: :delete} using button_to i manage to delete things, but confirmations dont work. Im guessing is something with bootstrap cuz in other project without it, destroy works just fine in link and button_to ..
I am on Rails 7.0.2.3 and I didn't have this issue. Maybe upgrading to this version of rails or higher might fix it,
@omokehinde dont work im using the rails 7.0.2.3 and i have the same issue but when i register a user
It works for me
<%= button_to 'Logout', destroy_user_session_path, method: :delete, form: {turbolink: false} %>
Hi everyone, This message is from Dec, 2022, I am currently making a rails app in which I do use devise, but certainly all of it works fine from registering a new user session to destroying the same. I am just a beginner at Ruby on Rails but this app needed nothing more.
This is what I did
<%= link_to "Log in", new_user_session_path %>
<%= link_to "Sign Up", new_user_registration_path %>
<%= link_to "Sign Out", destroy_user_session_path, 'data-turbo-method': :delete %>
I am attaching the repository You can check the application code to verify and let's close the issue finally.
Ran into this at the same time as you laughing
Quick fix, tl;dr
Add
:turbo_stream
as a navigational format. This line goes inconfig/initializers/devise.rb
. I haven't tested this extensively, but I think it should be fine.config.navigational_formats = ['*/*', :html, :turbo_stream]
More detail
A few lines from a trace starting with the offending line in registrations controller:
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/app/controllers/devise/registrations_controller.rb#L25
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/app/controllers/devise/registrations_controller.rb#L111-L113
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/lib/devise/controllers/helpers.rb#L264-L266
https://github.com/heartcombo/devise/blob/025b1c873491908b346e4d394f54481ec18fb02c/lib/devise.rb#L218-L220
Basically, requests in Rails 7 may come with format
:turbo_stream
rather than simply:html
. This causesis_navigational_format?
to be falsey and thusafter_sign_up_path_for
returnsnil
. Withlocation: nil
forresponds_with
, the redirect path resolves from the resource - in our case the user.I'm happy to open a PR for this, though someone with more familiarity with turbo should sanity check it.
This solution worked for me too!
My sample app is working fine with the changes I described here: How to customize Devise for Rails 7.0 and Turbo - DEV Community
I tested these behaviors:
- Sign up
- Sign in and sign out
- Edit account
- Reset password
- Cancel account
Wanted to confirm that the article that @JunichiIto posted/wrote worked successfully for me. Thank you!
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.
I have same issue after installing gem 'devise-security', '~> 0.17.0'
Not sure what causes it, but after I removed that gem everything works fine. I had problem in new
form (simple form gem, devise registrations controller).
@alex223125 I don't know much about that gem to help, sorry. They may need some tweak to work with Rails 7 and / or this latest Devise version.
What about the case where the object is not persisted? I'm getting the same error on this line
https://github.com/heartcombo/devise/blob/main/app/controllers/devise/registrations_controller.rb#L34
clean_up_passwords resource
set_minimum_password_length
respond_with resource
@botsarenthuman my first wild guess is that you're hitting something like this: https://github.com/heartcombo/devise/issues/5565#issuecomment-1457213530, where the object does not contain any errors associated with it (even if it's not persisted), so responders will try to redirect (it uses the presence of errors to determine how to respond), causing the error.