【问题标题】:On destroying session via Devise "Couldn't find User with 'id'=sign_out"通过设计销毁会话“找不到具有'id'=sign_out的用户”
【发布时间】:2017-07-26 12:29:58
【问题描述】:

我正在运行 Rails 5.1.2 和 Ruby 2.4.0。

我在 ApplicationController 中创建了一个名为 require_login 的方法,用于检查用户是否按顺序登录。当且仅当他们没有登录时,他们才会被转发到登录页面。

问题是当我将它们注销时,我收到以下错误

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

罪魁祸首是:

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

来自我的用户控制器。

这是我的代码:

应用控制器

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

用户控制器

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

我的layouts/topnav.html.erb,有人可以在其中退出

<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>

我的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

rake routes 也会输出以下内容:

                  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

如果某人未通过身份验证,我该怎么做才能将他们转发到登录页面?我怎样才能销毁他们的会话,以便在他们退出时正确地转发到登录页面?

【问题讨论】:

标签: ruby-on-rails ruby devise


【解决方案1】:

你做的一切都是对的。唯一缺少的是:method =&gt; :delete 电话。这是特定于 Rails 的,您需要 rails-ujs 或旧版本的 rails jquery_ujs 才能使其工作。

将此添加到您的 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

如果你不添加这个,method: :delete 调用将不起作用。如果您根本不想使用它,请更改 sign_out 以使用 GET

更改或将其添加到您的 config/initializers/devise.rb

config.sign_out_via = :get

如果仍然无法正常工作,那么您的 config/routes.rb 文件中的顺序有误。 devise_for :users 必须在resources :users 之前:

devise_for :users
resources :users

【讨论】:

  • 如果您使用 webpacker 进行资产编译,上述情况适用于 Rails 5.1 +,否则,jquery_ujs 方法仍然是要走的路。对我来说,我需要它,我没有使用sign_out_via = :get,但我必须确保我的设计退出链接包括method: :delete ala = link_to('Logout', destroy_user_session_path, class: 'nav__link', method: :delete)
【解决方案2】:

resources :usersdevise_for :users 是冲突所以

试试下面的代码:

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

另外,在您的config/initalizer/devise.rb 文件中

config.sign_out_via = :delete 更改为config.sign_out_via = :get

【讨论】:

  • 不幸的是,这导致No route matches [GET] "/users/sign_out"
  • 转到 config/initalizer/devise.rb 并将行 config.sign_out_via = :delete 更改为 config.sign_out_via = :get
  • 不,它们没有冲突。您必须先使用devise_for :users,然后再使用resources :users。我在不同的应用程序上使用 ruby​​ 2.4.x 和 2.5.x 以及 rails 4.2.x 到 5.1.5。
猜你喜欢
  • 2015-07-15
  • 2012-05-07
  • 2014-04-24
  • 2021-08-05
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
相关资源
最近更新 更多