You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails出现undefined method `session_token' for nil:NilClass错误求助

问题分析与解决方案:Ruby on Rails中undefined method 'session_token' for nil:NilClass错误

开发Ruby on Rails Web应用时,访问localhost:3000触发如下错误:

undefined method `session_token' for nil:NilClass

错误定位到current_user方法的这一行:

@current_user ||= user if session[:session_token] == user.session_token

完整的current_user方法代码:

def current_user
    if (user_id = session[:user_id])
        user = User.find_by(id: user_id)            
        @current_user ||= user if session[:session_token] == user.session_token         
    elsif (user_id = cookies.encrypted[:user_id])
        user = User.find_by(id: user_id)
        if user&.authenticated?(:remember, cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

错误原因

当session[:user_id]存在但对应的用户记录已被删除时,User.find_by(id: user_id)会返回nil,此时直接调用user.session_token相当于对nil对象调用方法,触发undefined method错误。

解决方案

1. 先校验用户存在性再比较令牌

修改current_user方法中session[:user_id]分支的代码,先确保user不为nil再进行令牌校验:

def current_user
    if (user_id = session[:user_id])
        user = User.find_by(id: user_id)            
        # 先检查user是否存在,再校验session_token
        @current_user ||= user if user && session[:session_token] == user.session_token         
    elsif (user_id = cookies.encrypted[:user_id])
        user = User.find_by(id: user_id)
        if user&.authenticated?(:remember, cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

2. 清理无效Session(可选优化)

如果发现user为nil,主动清除当前无效的Session数据,避免后续请求重复触发错误:

def current_user
    if (user_id = session[:user_id])
        user = User.find_by(id: user_id)            
        if user && session[:session_token] == user.session_token
            @current_user ||= user
        else
            # 清除无效的session数据
            session.delete(:user_id)
            session.delete(:session_token)
        end
    elsif (user_id = cookies.encrypted[:user_id])
        user = User.find_by(id: user_id)
        if user&.authenticated?(:remember, cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

3. 使用安全导航操作符简化校验

和remember分支写法保持一致,用&.避免nil对象调用方法:

def current_user
    if (user_id = session[:user_id])
        user = User.find_by(id: user_id)            
        @current_user ||= user if session[:session_token] == user&.session_token         
    elsif (user_id = cookies.encrypted[:user_id])
        user = User.find_by(id: user_id)
        if user&.authenticated?(:remember, cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

这种写法下,当user为nil时,user&.session_token会返回nil,此时session[:session_token] == nil逻辑上不成立,会跳过@current_user赋值,不会触发错误。

内容的提问来源于stack exchange,提问作者John Sall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:52:06