On destroying session via Devise “Couldn't find User with 'id'=sign_out”

百般思念 提交于 2020-07-31 04:51:22

问题


I'm running Rails 5.1.2 and Ruby 2.4.0.

I've created a method in the ApplicationController called require_login that checks if the user is logged in order not. If and only if they aren't logged in, they are forwarded to the login page.

The problem is that when I sign them out, I get the following error

ActiveRecord::RecordNotFound at /users/sign_out
Couldn't find User with 'id'=sign_out

With the culprit line being:

def show
    @user = User.find(params[:id]) # right here
    authorize @user
end

from my UserController.

This is my code:

ApplicationController

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?
  include Pundit

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:name])
  end

  def require_login
    unless signed_in?
      flash[:error] = "You must be logged in to access this section"
      redirect_to login_path # halts request cycle
    end
  end

end

UsersController

class UsersController < ApplicationController
  before_action :require_login

  def index
    @users = User.all
    authorize User
  end

  def show
    @user = User.find(params[:id])
    authorize @user
  end

  def update
    @user = User.find(params[:id])
    authorize @user
    if @user.update_attributes(secure_params)
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end

  def destroy
    user = User.find(params[:id])
    authorize user
    user.destroy
    redirect_to users_path, :notice => "User deleted."
  end

  private

  def secure_params
    params.require(:user).permit(:role)
  end

end

My layouts/topnav.html.erb where someone can sign out

<div class="row border-bottom">
    <nav class="navbar navbar-static-top white-bg" role="navigation" style="margin-bottom: 0">
        <div class="navbar-header">
            <a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
            <form role="search" class="navbar-form-custom" method="post" action="/">
                <div class="form-group">
                    <input type="text" placeholder="Search for something..." class="form-control" name="top-search" id="top-search" />
                </div>
            </form>
        </div>
        <ul class="nav navbar-top-links navbar-right">
            <li>
                <%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %>
            </li>
        </ul>
    </nav>
</div>

My routes.rb

Rails.application.routes.draw do
  root to: 'visitors#index'
  devise_for :users
  resources :users


  get "home/index"
  get "home/minor"
  root to: 'home#index'

end

Also rake routes outputs the following:

                  Prefix Verb   URI Pattern                    Controller#Action
                    root GET    /                              visitors#index
        new_user_session GET    /users/sign_in(.:format)       devise/sessions#new
            user_session POST   /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)      devise/sessions#destroy
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
           user_password PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
                         POST   /users/password(.:format)      devise/passwords#create
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
       user_registration PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy
                         POST   /users(.:format)               devise/registrations#create
                   users GET    /users(.:format)               users#index
                         POST   /users(.:format)               users#create
                new_user GET    /users/new(.:format)           users#new
               edit_user GET    /users/:id/edit(.:format)      users#edit
                    user GET    /users/:id(.:format)           users#show
                         PATCH  /users/:id(.:format)           users#update
                         PUT    /users/:id(.:format)           users#update
                         DELETE /users/:id(.:format)           users#destroy
                    page GET    /pages/*id                     high_voltage/pages#show

What can I do in order for a person to get forwarded to the Login page if they are not authenticated and how can I probably destroy their session so that when they sign out they are properly forwarded to the login page?


回答1:


resources :users and devise_for :users are conflict so

try below code:

routes.rb

Rails.application.routes.draw do
  root to: 'visitors#index'
  devise_for :users
  #resources :users //comment the users resources because its already used by devise_for or used some other resources for users


  get "home/index"
  get "home/minor"
  root to: 'home#index'

end

Additionally, in your config/initalizer/devise.rb file

Change config.sign_out_via = :delete to config.sign_out_via = :get




回答2:


You've done everything right. The only missing thing is the :method => :delete call. This is rails specific and you need rails-ujs or for older rails version jquery_ujs to make it work.

Add this to your app/assets/javascripts/application.js:

# for rails 5.1 or higher
//= require rails-ujs

# for rails 5.0 or lower
//= require jquery
//= require jquery_ujs

If you don't add this, the method: :delete call will not work. If you don't want to use it at all, then change sign_out to work with GET.

Change or add this to your config/initializers/devise.rb:

config.sign_out_via = :get

If it's still not working, then you have the wrong order in your config/routes.rb file. devise_for :users must be before resources :users:

devise_for :users
resources :users


来源:https://stackoverflow.com/questions/45327049/on-destroying-session-via-devise-couldnt-find-user-with-id-sign-out

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!