新手问题 RubyOnRailsTutorial 中,signout 和 current_user 的问题。

cloude9101 · 2013年12月22日 · 最后由 cloude9101 回复于 2013年12月22日 · 2728 次阅读

今天在做 Ruby on Rails Tutorial 时,遇到一个问题,请教一下,我是新手,还请大神们帮帮忙。谢谢。 在这本书的 Sample_App 中,app/helpers/sessions_helper.rb 该文件定义了登入登出以及 cookies 相关的方法。 我是按照书里一步步来的,现在情况是在 sign out 时会出错,提示 current_user 为 nil,没有 update_attribute 方法。
但是我试了如果把 cookies.delete 这个方法放到 current_user.update_attribute 后面,就没有问题。 请问这是怎么回事呢?希望同时说明一下这其中的 self 是代表 SessionsController 的实例吗?为什么在 sign_out 方法里 update_attribute 时不用 self 呢?

该文件的完整代码如下:

module SessionsHelper

    def sign_in(user)
        remember_token = User.new_remember_token
        cookies.permanent[:remember_token] = remember_token
        user.update_attribute(:remember_token, User.encrypt(remember_token))
        self.current_user = user
    end

    def current_user=(user)
        @current_user = user
    end

    def current_user
        remember_token = User.encrypt(cookies[:remember_token])
        @current_user ||= User.find_by(remember_token: remember_token)
    end

    def signed_in?
        !current_user.nil?
    end

    def sign_out
        cookies.delete(:remember_token)
        current_user.update_attribute(:remember_token, User.encrypt(User.new_remember_token))
        self.current_user = nil
    end
end

因为定义了current_user=这个方法,所以在调用的时候用self.current_user=来调用,避免和current_user=产生混淆,不知道是不是这样的?

局部变量标识符与方法调用相同的时候,会优先认为一个局部变量。

从 current_user 方法可以看出,是通过 remember_token 来查找用户的,所以在 sign_out 中,先删除 remember_token 的话,current_user 当然找不到了,所以为 nil。

self 只有在进行复制操作的时候,也就是 method_name = 时,为了防止其变成一个局部变量复制操作才需要加上 self,变为 self.method_name =,其他情况下是不需要加的

#3 楼 @reyesyang 谢谢回复,以及楼上两位 sign_in 之后,@current_user = user,这样

@current_user ||= User.find_by(remember_token: remember_token)

这个方法看起来好像就算 remember_token 删掉,也没问题吧。

self 那个明白了。

#4 楼 @cloude9101 这个就取决于你在调用 sign_out 方法之前有没有调用过 current_user 方法了

#5 楼 @reyesyang sign_out 之前 是调用过 sign_in 方法的,所以 @current_user应该不为 nil 吧。 如果 @current_user 不为 nil 的话,不管 sign_out 之前有没有调用过 current_user 方法,在 sign_out 里调用 current_user 方法,都不应该返回 nil 吧。

sign_out 之前调用过 sign_in 方法,你意思应该是在登出前先登录了一次吧?如果是这样的话,因为两次调用不是在一次请求中,登录是登录的请求,登录请求中是给 @current_user 赋了值,但该请求完毕后,所有实例变量和请求一并就销毁了。和登出请求是无关的。

#7 楼 @reyesyang 原来如此,懂了,谢谢...

需要 登录 后方可回复, 如果你还没有账号请 注册新账号