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
相关产品推荐
相关产品推荐

