Rails - “记住我”的能力

时间:2011-06-22 01:27:49

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

我无法理解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

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

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

如果用户已登录,则@current_user方法已定义sign_in,因此current_user方法中的|| =无意义。

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

简而言之,如果current_user方法返回@current_user(如果已定义),则为nil,否则使用传统的访问方法不会简单得多:

def current_user
    return @current_user
end
迈克尔·哈特尔的书说,这样做是没用的,因为用户的登录状态会被遗忘。为什么会这样?有人可以解释为什么我们不这样做,而是使用上面发布的更复杂的版本?

2 个答案:

答案 0 :(得分:2)

仅当您使用登录表单实际登录时,才会调用

sign_in。之后,您必须使用每个请求的cookie值设置当前用户。

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

答案 1 :(得分:2)

该行

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应用程序中查看维护状态,以获取有关为什么必须跳过这些环节的更多信息。