我无法理解 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_salt
User 模型中的方法通过第一个参数(id)找到用户,如果定义了用户并且其 salt 等效于第二个参数(salt),则返回用户,否则返回 nil。
我无法理解为什么我们要花这么多时间来测试用户是否已经登录:
如果用户已登录,@current_user
则该方法已定义,sign_in
因此该方法中的 ||=current_user
没有意义。
如果用户未登录,该方法中的 ||= 运算符将返回该current_user
方法返回的值user_from_remember_token
,但由于 cookies.signed[:remember_token] 将为 nil,User.authenticate_with_salt
因此将传递 [nil,nil] 参数并且将返回 nil,因此该current_user
方法将返回 nil。
简而言之,如果该current_user
方法返回 @current_user(如果它已定义,则返回 nil),那么仅使用传统的访问器方法会不会更简单:
def current_user
return @current_user
end
Michael Hartl 的书说这样做是没有用的,因为用户的登录状态会被遗忘。为什么会这样???有人可以解释为什么我们不这样做,而是使用上面发布的更复杂的版本吗?