Devise: Why doesn't my logout link work?
the problem: In a nutshell, when I try to install a logout link to my app it fails to work. Here's as much context as I can think to put here (if you want anything else, please poke me)...
I've got this in a haml view:
= link_to("Logout", destroy_user_session_path, :method => :delete)
It generates this in the view:
<a href="/users/sign_out" data-method="delete" rel="nofollow">Logout</a>
I verified that in my config/initializers/devise.rb I have this setting uncommented and correct:
config.sign_out_via = :delete
I validated the following route:
destroy_user_session DELETE /users/sign_out(.:format) {:action=>"destroy", :con开发者_JS百科troller=>"devise/sessions"}
I also have this bit of trickery in my routes.rb, and I suspect this is related to my issue:
devise_for :users, :controllers => {:sessions => "devise/sessions", :registrations => "users"}
resources :users
This last bit is because I want to manage (edit, create and delete) users in my own controller.
The error message I'm getting is as follows:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with ID=sign_out
Rails.root: /home/jaydel/projects/mbsquared-projects/Wilson-Goldrick
app/controllers/users_controller.rb:16:in `show'
In my server logs I see this for the request:
Started GET "/users/sign_out" for 127.0.0.1 at 2011-08-04 13:08:51 -0500
Processing by UsersController#show as HTML
Parameters: {"id"=>"sign_out"}
Anyone have any ideas?
The correct way to fix this, REST-wise, would be to change your logout links to use the DELETE method. It's a very easy fix, changing this:
link_to "Log out", destroy_user_session_path
to this:
link_to "Log out", destroy_user_session_path, :method => :delete
I had the same problem with rails 3.2 when I deleted from application.js
this line:
//= require jquery_ujs
So, I think you have to insert this line in your application.js
if you haven't it there.
PS. This behavior means that rails adapter for jquery
doesn't function. So you should make sure if it is loaded in your html in browser. You should test it in development mode because you will have compressed js in production and it will be very difficult to find something there.
The problem lies in the fact that in your logs the signout request is a GET request.
Started GET "/users/sign_out"
But the signout route is a DELETE
destroy_user_session DELETE /users/sign_out(.:format)
The reason why you are getting the exception is that is it getting confused with one of the routes created by resources :users
which would be something like
edit_user GET /users/(:id)(.:format) {:action=>"edit", :controller=>"users"}
Basically 'sign_out' is being mistaken as a id.
I'm not sure why the delete link is not going through as a DELETE request. Though changing
config.sign_out_via = :delete
to be :get
might solve the problem.
You need both
link_to "Log out", destroy_user_session_path, method: :delete
&& these included in application.js
//= require jquery
//= require jquery_ujs
. Obviously, don't forget to add this to Gemfile if for some reason it is not there.
gem 'jquery-rails'
I've tried all the solutions mentioned here but the true solution to this issue is the following :
<%= link_to "Sign Out", destroy_user_session_path, 'data-turbo-method': :delete%>
It works if it doesn't just refresh or restart the server.
This is an old question but the accepted answer is not the proper way to solve this issue (although it is a good diagnosis of the problem).
When I ran into this today my routes file appeared as:
root :to => 'welcome#index'
resources :users
devise_for :users
As mentioned by Olives the resources statement is simply causing /users/anything to trip up. I simply needed to reverse the ordering of my routes...
root :to => 'welcome#index'
devise_for :users
resources :users
jQuery is required in order to perform the request with DELETE. Make sure you didn't drop it from your application.js.
Since the OP mentioned devise and this problem also happened to me, I just wanted to chime in. @Ross Allen had the correct answer when you don't want to use jQuery_ujs. Rails provides a couple of helpers to solve this without jQuery.
This is Ross's answer but using Devise's current_user model:
<%= form_for(current_user,
url: destroy_user_session_path, html: { method: :delete }) do |f| %>
<%= f.submit "Log out" %>
<% end %>
Or the more succinct button_to helper that creates a similar form:
<%= button_to "Log out", destroy_user_session_path, method: :delete %>
This is an old question, but I wanted a way that required no JavaScript. Rails enables "DELETE" like requests with a hidden input that sets method
to delete
. Use a real <form>
, and let Rails generate the necessary hidden inputs:
<%= form_for(resource, as: resource_name,
url: destroy_user_session_path, html: { method: :delete }) do |f| %>
<%= f.submit "Log out" %>
<% end %>
the above generates something like:
<form accept-charset="UTF-8" action="/users/sign_out" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
<input name="_method" type="hidden" value="delete">
<input name="authenticity_token" type="hidden" value="1234">
</div>
<input name="commit" type="submit" value="Log out">
</form>
I've checked all this solutions, but no one has worked for me. Finally I found that in header I deleted two lines including application tags and csrf meta
So, If someone have this problem with no sollution at this point - check if you have in header of the page (HAML notation)
= javascript_include_tag 'application'
= csrf_meta_tags
I had to go about this in a different manner as my application.rb had:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
and was still failing. It turns out I needed to set config.serve_static_assets = true
in /environment/development, test and production.rb. This link was what helped me figure it out.
You also have to check, is resources :users
under devise_for :users
and is the link method delete
link_to "Logout", destroy_user_session_path, method: :delete
if both are right, your logout button should work
I agree that it's more restful to use the http DELETE method, I like to create a simple endpoint to destroy a user session with a GET method.
by adding this to config/routes.rb
devise_scope :user do
get '/logout', :to => 'sessions#destroy'
end
If your are also having more than one jquery sources in your rails app you need to use the default one specified in the Gemfile
make sure in your Gemfile you have this
gem 'jquery-rails'
and in your assets you do not have any other JQuery source files.
in my case I had a second JQuery file other than the default as declared in the Gemfile so it caused conflicts.
if you previously had those source, be sure to precompile assets again if you had previously done so
If you're finding this problem in production and you're using the asset pipeline, you often need to:
rake assets:clobber
in order to clear out your public assets. Then rake assets:precompile
before committing and pushing your code (unless your push also precompiles, aka Heroku).
the reason may be in the wrong order connection bootstrap-sprockets
the correct order:
// app/assets/javascripts/application.js
...
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require_tree .
As mentioned by Tombart above, the answer for me was putting back the rails-ujs call in my application.js file.
//= require rails-ujs
//= require turbolinks
I had initially removed them to stop errors from having my scripts in the footer be re-evaluated. My workaround was to create a footer.js compile file with the resources I wanted in the footer.
//= require jquery-3.2.1.min
//= require jquery-ui-1.12.1.min
//= require materialize
//= require init
Then in my /initializers/assets.rb file adding a precompile
Rails.application.config.assets.precompile += %w( footer.js )
Then you can call the following in your layout/application.html.erb file.
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'footer' %>
I keep the application line in my header, and added my new "footer" call before the end of my body tag.
1) I feel u may need to install below gem, the request with method: :delete will work else it may go as get
https://github.com/rails/jquery-rails
2) Add this two below lines in application.js
//= require jquery
//= require jquery_ujs
Stop the server
yarn add "@rails/ujs"
yarn add turbolinks
yarn add @rails/activestorage
My application.js
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
Start the server
精彩评论