【问题标题】:Rails -- "remember me" capabilityRails——“记住我”的能力
【发布时间】:2011-09-20 00:08:59
【问题描述】:

我无法理解 Michael Hartl 编写的 Ruby on Rails 教程中“记住我”的实现。他创建了一个带有登录方法的 SessionsHelper 模块,其中包含以下内容:

module SessionsHelper

    def sign_in(user)
        cookies.permanent.signed[:remember_token] = [user.id, user.salt]
        current_user = user
    end

    def current_user=(user)
        @current_user = user
    end

    def current_user
        return @current_user ||= user_from_remember_token
    end

    private
        def user_from_remember_token
            #passes array of length two as a parameter -- first slot contains ID,
            #second contains SALT for encryption
            User.authenticate_with_salt(*remember_token)
        end

        def remember_token
            #ensures return of a double array in the event that
            #cookies.signed[:remember_token] is nil.
            cookies.signed[:remember_token] || [nil,nil]
        end

end

注意:authenticate_with_saltUser 模型中的方法通过第一个参数(id)查找用户,如果用户已定义且其 salt 等效于第二个参数(salt) 则返回用户,否则返回 nil。

我无法理解为什么我们要花这么多时间来测试用户是否已经登录:

如果用户登录,@current_user 已经由 sign_in 方法定义,因此 current_user 方法中的 ||= 没有意义。

如果用户未登录,current_user 方法中的 ||= 运算符将返回 user_from_remember_token 方法返回的值,但由于 cookies.signed[:remember_token] 将为 nil,@ 987654328@ 将传递 [nil,nil] 参数并返回 nil,因此,current_user 方法将返回 nil。

简而言之,如果current_user 方法在定义时返回@current_user,否则返回nil,那么只使用传统的访问器方法不是更简单吗:

def current_user
    return @current_user
end

Michael Hartl 的书中说这样做是没有用的,因为用户的登录状态会被遗忘。为什么会这样???有人能解释一下为什么我们不这样做,而是使用上面发布的更复杂的版本吗?

【问题讨论】:

    标签: ruby ruby-on-rails-3 remember-me


    【解决方案1】:

    线

    return @current_user ||= user_from_remember_token
    

    是一种惰性初始化形式,以避免在实际需要之前初始化@current_user 变量。 @current_user 永远不会在第一次调用此函数时被初始化,但它会在每次连续调用时都有一个值(假设 user_from_remember_token 返回的值不是 nil)。

    他本来可以写的

    def current_user
      return user_from_remember_token
    end
    

    此代码将始终将当前用户初始化为它从 cookie 中读取的任何内容。这会正常运行,但他可能想避免重复读取 cookie,所以他只读取一次并将其存储在一个变量中。

    他做不到

    def current_user
      return @current_user
    end
    

    因为@current_user 变量不会跨页面请求持续存在。页面呈现并发送回客户端后,@current_user 变量被销毁,其值被遗忘。

    希望这会有所帮助。查看在 Web 应用程序中维护状态,以获取有关为什么有必要跳过这些环节的更多信息。

    【讨论】:

      【解决方案2】:

      sign_in 仅在您实际使用登录表单登录时调用。之后,您必须使用每个请求的 cookie 值设置当前用户。

      因此,当用户登录并打开页面时,第一次调用 current_user 时,它将填充 @current_user 实例变量并将其用于进一步的 current_user 调用。

      【讨论】:

      • 但是一旦@current_user 由sign_in 设置,它就不会一直存在吗?比如为什么我们不能只使用实例变量@current_user 而不是cookie?它们之间的主要区别是什么?
      • 就像 Michael Venable 的回答所说:“@current_user 变量不会在页面请求中持续存在”。所以第一次在页面请求中使用current_user方法时,需要从cookie中获取用户信息。
      猜你喜欢
      • 2012-03-22
      • 1970-01-01
      • 2011-12-01
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      相关资源
      最近更新 更多