4
votes

I'm going in circles with a bit of code in section 8.4.4 ("Two Subtle Bugs") in the 3rd edition of Michael Hartl's Rails tutorial. (Link to this section of the text: https://www.railstutorial.org/book/log_in_log_out#sec-two_subtle_bugs[1])

Specifically I'm confused about the following text/code:

"The second subtlety is that a user could be logged in (and remembered) in multiple browsers, such as Chrome and Firefox, which causes a problem if the user logs out in one browser but not the other. For example, suppose that the user logs out in Firefox, thereby setting the remember digest to nil (via user.forget in Listing 8.38). This would still work in Firefox, because the log_out method in Listing 8.39 deletes the user’s id, so the user variable would be nil in the current_user method:

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

As a result, the expression

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

returns false due to short-circuit evaluation."

For this question, let's stick with Firefox and not worry about the second browser bug. Hartl seems to be saying the following:

  1. The log_out method sets the remember digest to nil in the database.
  2. The log_out method deletes the user_id stored in both the session and cookie.
  3. A subsequent call to the current_user method from within the same browser would not raise an error because "the user variable would be nil in the current_user method." This would cause short-circuiting of the expression user && user.authenticated?(cookies[:remember_token]).

My questions is how this could ever happen. If the log_out method works as stated, shouldn't the line elsif (user_id = cookies.signed[:user_id]) be false on subsequent calls? The elsif block wouldn't run and the user variable would never be set. In fact both conditionals in the current_user method would be false and the method would return nil. There would be no short-circuiting based on the user variable.

Can the short-circuit evaluation that he describes take place?

2

2 Answers

1
votes

You are correct that the short-circuit does not occur since

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

does not run and the user variable would never be set IN FIREFOX., since the cookie is delted in 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

However, that doesn't change Hartl's main point that the user was also logged in via Chrome, which is where the error occurs.

0
votes

Hartl has recently edited that section of the book (as of early March 2015), and now the current way he describes it doesn't seem to have this error.