Rails教程:8.4.4节中的短路评估

时间:2014-11-04 15:14:42

标签: ruby-on-rails railstutorial.org

我将在第4版的Michael Hartl的Rails教程的第8.4.4节(“两个微妙的错误”)中加入一些代码。 (链接到文本的这一部分:https://www.railstutorial.org/book/log_in_log_out#sec-two_subtle_bugs[1]

具体来说,我对以下文字/代码感到困惑:

  

“第二个微妙之处在于用户可以登录(和   记住了)在多个浏览器中,例如Chrome和Firefox   如果用户在一个浏览器中注销而不是,则会导致问题   其他。例如,假设用户在Firefox中注销   将remember digest设置为nil(通过代码清单8.38中的user.forget)。   这仍然适用于Firefox,因为在log_out方法中   代码清单8.39删除了用户的id,因此用户变量为nil   在current_user方法中:

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

结果,表达式

     

user && user.authenticated?(cookies[:remember_token])

     由于短路评估,

返回false。“

对于这个问题,让我们坚持使用Firefox而不用担心第二个浏览器错误。哈特尔似乎在说以下内容:

  1. log_out方法将记忆摘要设置为数据库中的nil。
  2. log_out方法删除存储在会话中的user_id 和饼干。
  3. 从同一浏览器中对current_user方法的后续调用不会引发错误,因为“current_user方法中的用户变量将为nil”。这会导致表达式user && user.authenticated?(cookies[:remember_token])短路。
  4. 我的问题是如何发生这种情况。如果log_out方法按照规定工作,那么后续调用中的行elsif (user_id = cookies.signed[:user_id])是否应该为false? elsif块不会运行,用户变量永远不会被设置。实际上,current_user方法中的两个条件都是false,并且该方法将返回nil。根据用户变量不会出现短路。

    他描述的短路评估可以进行吗?

2 个答案:

答案 0 :(得分:1)

你是正确的,因为

没有发生短路
  

elsif(user_id = cookies.signed [:user_id])

未运行且用户变量永远不会设置为 IN FIREFOX。,因为Cookie已在Sessions Helper中删除:

# Forgets a persistent session.
  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

  # Logs out the current user.
  def log_out
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end

然而,这并没有改变Hartl的主要观点,即用户也是通过 Chrome 登录的,这是发生错误的地方。

答案 1 :(得分:0)

Hartl最近编辑了本书的那一部分(截至2015年3月初),现在他描述它的当前方式似乎没有这个错误。