No route matches [GET] "/users/sign_out"

Viewed 41755

Here is my actual error: No route matches [GET] "/members/sign_out" Since most people will use "users" I thought it would be more helpful to have that in the title. At any rate, I am essential unable to logout. I can successfully edit my member profile.

I am using devise 1.4.2 and Rails 3.1.0.rc4. Also, I have generated two separate devise models - one called "members" and the other called "admins". I was able to register and log into both of them (simultaneously) by manually navigating to the correct URL path (i.e., localhost:3000/admins/sign_in/). I created some links within my application.html.haml layout file by following this RailsCast on Devise. I am aware that it only addresses signin/signout links for "members."

If I click on the signout link I get the above error. This occurs if I manually navigate to either signout URL (i.e., localhost:3000/admins/sign_out/).

Can someone tell me why this is happening? Below are the various related files. And of course, I'm a newbie...

rake routes output:

    j(film_repo)$ rake routes
        new_member_session GET    /members/sign_in(.:format)       {:action=>"new", :controller=>"devise/sessions"}
            member_session POST   /members/sign_in(.:format)       {:action=>"create", :controller=>"devise/sessions"}
    destroy_member_session DELETE /members/sign_out(.:format)      {:action=>"destroy", :controller=>"devise/sessions"}
           member_password POST   /members/password(.:format)      {:action=>"create", :controller=>"devise/passwords"}
       new_member_password GET    /members/password/new(.:format)  {:action=>"new", :controller=>"devise/passwords"}
      edit_member_password GET    /members/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"}
                           PUT    /members/password(.:format)      {:action=>"update", :controller=>"devise/passwords"}
cancel_member_registration GET    /members/cancel(.:format)        {:action=>"cancel", :controller=>"devise/registrations"}
       member_registration POST   /members(.:format)               {:action=>"create", :controller=>"devise/registrations"}
   new_member_registration GET    /members/sign_up(.:format)       {:action=>"new", :controller=>"devise/registrations"}
  edit_member_registration GET    /members/edit(.:format)          {:action=>"edit", :controller=>"devise/registrations"}
                           PUT    /members(.:format)               {:action=>"update", :controller=>"devise/registrations"}
                           DELETE /members(.:format)               {:action=>"destroy", :controller=>"devise/registrations"}
         new_admin_session GET    /admins/sign_in(.:format)        {:action=>"new", :controller=>"devise/sessions"}
             admin_session POST   /admins/sign_in(.:format)        {:action=>"create", :controller=>"devise/sessions"}
     destroy_admin_session DELETE /admins/sign_out(.:format)       {:action=>"destroy", :controller=>"devise/sessions"}
            admin_password POST   /admins/password(.:format)       {:action=>"create", :controller=>"devise/passwords"}
        new_admin_password GET    /admins/password/new(.:format)   {:action=>"new", :controller=>"devise/passwords"}
       edit_admin_password GET    /admins/password/edit(.:format)  {:action=>"edit", :controller=>"devise/passwords"}
                           PUT    /admins/password(.:format)       {:action=>"update", :controller=>"devise/passwords"}
 cancel_admin_registration GET    /admins/cancel(.:format)         {:action=>"cancel", :controller=>"devise/registrations"}
        admin_registration POST   /admins(.:format)                {:action=>"create", :controller=>"devise/registrations"}
    new_admin_registration GET    /admins/sign_up(.:format)        {:action=>"new", :controller=>"devise/registrations"}
   edit_admin_registration GET    /admins/edit(.:format)           {:action=>"edit", :controller=>"devise/registrations"}
                           PUT    /admins(.:format)                {:action=>"update", :controller=>"devise/registrations"}
                           DELETE /admins(.:format)                {:action=>"destroy", :controller=>"devise/registrations"}
                     films GET    /films(.:format)                 {:action=>"index", :controller=>"films"}
                           POST   /films(.:format)                 {:action=>"create", :controller=>"films"}
                  new_film GET    /films/new(.:format)             {:action=>"new", :controller=>"films"}
                 edit_film GET    /films/:id/edit(.:format)        {:action=>"edit", :controller=>"films"}
                      film GET    /films/:id(.:format)             {:action=>"show", :controller=>"films"}
                           PUT    /films/:id(.:format)             {:action=>"update", :controller=>"films"}
                           DELETE /films/:id(.:format)             {:action=>"destroy", :controller=>"films"}
                      root        /                                {:controller=>"films", :action=>"index"}

routes.rb

FilmRepo::Application.routes.draw do
  devise_for :members

  devise_for :admins

  resources :films

  root :to => 'films#index'
end

admin.rb (model)

class Admin < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, and :omniauthable
  devise :database_authenticatable, :registerable, :timeoutable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me
end

member.rb (model)

class Member < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me
end

application.html.haml

!!!
%html
    %head
        %title Film Repo
        = stylesheet_link_tag 'compiled/screen.css', :media => 'screen, projection'
        = stylesheet_link_tag 'compiled/print.css', :media => 'print'
        /[if lt IE 8]
            = stylesheet_link_tag 'compiled/ie.css', :media => 'screen, projection'
            = csrf_meta_tag
    %body.bp
        #container
            #user_nav
                - if member_signed_in?
                    Signed in as #{current_member.email}. Not you?
                    \#{link_to "Sign out", destroy_member_session_path}
                - else
                    = link_to "Sign up", new_member_registration_path
                    or #{link_to "sign in", new_member_session_path}
                - flash.each do |name, msg|
                    = content_tag :div, msg, :id => "flash_#{name}"
            = yield
26 Answers

If you want to use :delete method for security reasons and not be dependent on jquery-ujs you can use button_to instead of link_to, like:

button_to "Log out", destroy_user_session_path, method: :delete

if using link_to you must be sure to have javascript active:

Note that if the user has JavaScript disabled, the request will fall back to using GET.

As seen in docs

= link_to "Sign out", destroy_user_session_path,:method => :delete

will NOT work instead use this,

= link_to "Sign out", destroy_user_session_path,:method => 'delete'

should do the trick or worse case add require jquery_ujs in your application.js

In Rails 6:

I just changed the link_to to button_to, and the 'sign out' works properly

<%= button_to "Sign out", destroy_user_session_path, method: :delete %>

I am using rails version 5. I encounter this problem also. The simple fix I did was to changing the devise configuration in initializes to the default.

From :

config.sign_out_via = :get

To :

config.sign_out_via = :delete

In rails 7, you need to add data: { turbo_method: :delete" } to link_to. So the link_to would look like this

<%= link_to "Log out", destroy_user_session_path, data: { turbo_method: :delete } %>

Keep your devise.rb using the correct HTTP method:

# good 
config.sign_out_via = :delete

# bad
config.sign_out_via = :get

Use button_to instead of link_to

# good 
= button_to "Sign Out", destroy_user_session_path, method: :delete

# bad
= link_to "Sign Out", destroy_user_session_path, method: :delete"

If you are using bootstrap (keep it classy)

= link_to "Sign Out", destroy_user_session_path, method: :delete, class: "btn btn-default btn-sm"

Ref: github.com/heartcombo/devise/issues/4570#issuecomment-740812109

devise_for :users

devise_scope :user do  
   get '/users/sign_out' => 'devise/sessions#destroy'     
end

That works for me

I believe this error is due to devise library template not aligned with changes on rails 7,

In short, you are not sending the request in method delete as expected due to the Javascript library that does that is now missing.

you can change :

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

with

<%= link_to "Sign out", destroy_user_session_path, data: { "turbo-method": :delete }, class: "btn btn-danger ml-3" %>

And it will work again

This worked for me: <%= link_to 'Sign out', destroy_user_session_path, data: { turbo_method: :delete } %>

Related