Rails——“记住我”能力
我无法理解 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),如果定义了用户并且其盐相当于第二个参数(盐),则返回用户,否则返回 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 的书说这样做会是无用,因为用户的登录状态会被忘记。为什么会这样???有人可以解释一下为什么我们不这样做而是使用上面发布的更复杂的版本吗?
I am having trouble understanding the implementation of "Remember Me" in the Ruby on Rails Tutorial by Michael Hartl. He creates a SessionsHelper module with methods for signing in, containing the following:
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
NOTE: The authenticate_with_salt
method in the User model finds the user by the first parameter (the id) and if the user is defined and its salt is equivalent to the second parameter (the salt) then the user is returned, otherwise nil is returned.
I am having trouble understanding why we go to such lengths to test if the user has already been signed in:
In the event that the user is signed in, @current_user
is already defined by the sign_in
method and therefore the ||= in the current_user
method is meaningless.
In the event that the user is not signed in, the ||= operator in the current_user
method returns the value returned by the user_from_remember_token
method, but since cookies.signed[:remember_token] would be nil, User.authenticate_with_salt
would be passed the [nil,nil] argument and would return nil, and therefore, the current_user
method would return nil.
In short, if the current_user
method is returning @current_user if it is defined and nil otherwise, wouldn't it be much simpler to just use the conventional accessor method:
def current_user
return @current_user
end
Michael Hartl's book says that doing this would be useless because the user's sign in status would be forgotten. Why would that be the case??? Can someone please explain why we do not do this and instead use the much more intricate version posted above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
sign_in
仅在您实际使用登录表单登录时调用。之后,您必须使用每个请求的 cookie 值来设置当前用户。因此,当用户登录并打开页面时,第一次调用
current_user
时,它将填充@current_user
实例变量并将其用于进一步的current_user
代码>调用。sign_in
is only called when you actually sign in using the login form. After that you have to set the current user using the cookie values for each request.So when the user is signed in and opens a page, first time
current_user
is called it will populate the@current_user
instance variable and use it for furthercurrent_user
calls.该行
是延迟初始化的一种形式,以避免在实际需要之前初始化
@current_user
变量。 @current_user 第一次调用此函数时永远不会被初始化,但每次连续调用时它都会有一个值(假设 user_from_remember_token 返回 nil 以外的值)。他本可以编写
此代码将始终将当前用户初始化为从 cookie 中读取的任何内容。这会表现正确,但他可能想避免重复读取 cookie,因此他执行一次并将其存储在变量中。
他不能这样做
,因为 @current_user 变量不会跨页面请求持续存在。页面呈现并发送回客户端后,@current_user 变量将被销毁,并且其值将被遗忘。
希望这有帮助。研究维护 Web 应用程序中的状态,以获取有关为什么需要跳过这些障碍的更多信息。
The line
is a form of lazy initialization to avoid initializing the
@current_user
variable until it is actually needed.@current_user
will never be initialized the first time this function is called, but it will have a value on each successive call (assuminguser_from_remember_token
returns something other than nil).He could have written
This code will always initialize the current user to whatever it reads from the cookie. This would behave correctly, but he probably wanted to avoid repeatedly reading the cookie, so he does it once and stores it in a variable.
He cannot do
because the @current_user variable does not persist across page requests. After the page renders and is sent back to the client, the @current_user variable is destroyed and its value is forgotten.
Hope this helps. Look into maintaining state in web applications for more information on why it's necessary to jump through these hoops.