【问题标题】:Michael Hartl chapter 8.3 logging out sessionsMichael Hartl 第 8.3 章注销会话
【发布时间】:2017-06-13 19:41:42
【问题描述】:

我正在阅读 Michael Hartl 的 The Ruby on Rails 教程,第 8.3 章注销会话,但我不明白删除 session[:user_id] 如何也可以删除 @current_user

这里是会话控制器:

class SessionsController < ApplicationController
  def new

  end

  def create
    user =User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in(user)
      redirect_to user
    else
      #flash.now will only flash once - if a new request or view is rendered,the flash will go away now
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end

  end

  def destroy

    log_out
    redirect_to root_path

  end

end

这里是登录和注销助手的 SessionsHelper:

module SessionsHelper

    def log_in(user)

        session[:user_id] = user.id
    end

    def current_user
        #find the user if @user is not defined yet, or else, just keep the current user
        #that way we dont have to do a database search every time current_user is called
        @current_user ||= User.find_by(id: session[:user_id])
    end

    def logged_in?
        !current_user.nil?

    end
    def log_out
        session.delete(:user_id)
    end
end

按照我的理解,一旦登录后定义了@current_user,即使session[:user_id] 已被删除,因为它被设置为自身,变量不应该仍然存在吗?

@current_user ||= User.find_by(id: session[:user_id])

据我所知,没有删除@current_user 变量的操作。但是当我在调试器中测试它时,我可以看到一旦有人注销,@current_user 就变成了nil

谁能给我解释一下机制?

【问题讨论】:

    标签: ruby-on-rails ruby session logout railstutorial.org


    【解决方案1】:

    session 在请求之间持续存在。但是实例变量@current_user 只持续一个请求的长度。当destroy 操作重定向到root_path 时,这就是将加载根页面的新请求的开始。

    您可能想尝试一下,看看从会话中清除 user_id 并不会清除实例变量:

    def destroy
      # Test code to initialize @current_user
      current_user
      Rails.logger.debug("@current_user before: #{@current_user.inspect}")
    
      log_out
    
      # Test code to check @current_user after updating session
      Rails.logger.debug("@current_user after: #{@current_user.inspect}")
    
      redirect_to root_path
    end
    

    然后检查log/development.log 中的结果。 @current_user 将在 log_out 之后仍然存在,但它会在请求结束时消失。

    【讨论】:

    • 谢谢,这很有用!但是,我试过这个: >def destroy >Rails.logger.debug("@current_user value: #{@current_user.inspect}") log_out >Rails.logger.debug("@current_user value: #{@current_user.inspect} ") redirect_to root_path end >但我知道@current_user 在这两个方面都为零:由 SessionsController#destroy 作为 HTML 参数处理:{"authenticity_token"=>"OjnBcB5CAdUbuGmW68lzlkVqx8B3R7f+6ZTdUGBj61XC/vuFa9Vp7oAodT6RtkFNVTduPgp0hB5UaMV nil >@current_user 值:nil 看起来好像从未设置过 current_user?
    • 对不起,你说得对。我已经更新了答案中的示例。 destroy 操作不需要知道当前用户,因此它从不设置它。任何需要当前用户的请求都会调用current_user helper 方法,@current_user 从那时起一直存在到请求结束。
    • 好的,我明白了,谢谢!还有一个后续问题 - 所以,在我的 _header.html.erb 部分中,我使用了这个:&lt;li&gt;&lt;%= link_to "Profile", current_user %&gt;&lt;/li&gt; 应该设置@current_user,对吗?那么为什么我需要在控制器中再次调用 current_user 来设置它呢?
    • 控制器creates a response 的两个常见选项是渲染或重定向。 detroy 操作未呈现。相反,它只是重定向到根路径。所以_header.html.erb中的代码没有被destroy执行。如果您在 log/development.log 中查找“渲染”引用,您可以看到给定控制器操作渲染了哪些模板。
    猜你喜欢
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多