Rails教程:实例变量的使用

Rails Tutorial: use of instance variables

我在 Rails 教程的第 8.4.3 - Forgetting Users 部分。

# app/helpers/session_helper.rb
module SessionsHelper
...
  # Returns the user corresponding to the remember token cookie.
  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

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

current_user 方法中,我们将用户分配给 @current_user 实例变量。我不明白为什么我们不在 log_out 方法中使用相同的实例变量(在该方法中 current_user 没有前缀 @ 符号)。 current_user 是从哪里来的,因为它没有作为参数传递给该方法?

Ruby 在方法调用和局部变量之间没有区别。这就是为什么 current_user 可能看起来两者都一样的原因。 在您的情况下,它是定义的方法。

您实际上可以同时使用 @current_usercurrent_user,因为该方法的返回值应等于 @current_user.

current_user 是在您发布的页面片段中定义的方法。

@current_user 是 BY current_user

设置的实例变量

所以当你看代码时:

# Defines a method called log_out
def log_out
  # Calls the 'forget' method on the result of the 'current_user' method,
  #   which sets @current_user
  forget(current_user)
  # Deletes the session variable named 'user_id'
  session.delete(:user_id)
  # Resets @current_user to nil, because there should no longer be one
  @current_user = nil
end

如果我想换个角度看,我可以说:

def log_out
  # Sets @current_user
  current_user
  # Calls the forget method on the variable @current_user
  forget(@current_user)
  session.delete(:user_id)
  @current_user = nil
end

但是我无法将最后一行更改为 current_user = nil 而不是 @current_user = nil,因为这样我就将 nil 值分配给方法的名称而不是实例变量。

方法调用和变量在 Ruby 中看起来如此相似的部分原因是一切都作为对象处理,因此方法 本质上 只是一个变量,其值是一段代码(与我们所说的 "block" 和方法存在技术差异,但从概念上讲这是一个不错的类比)。当我们定义一个方法时,我们将它保存到一个或多或少的变量中。因此,如果我们考虑方法 "current_user",我们可能会将其视为一个变量 "current_user",其值为 forget(current_user); session.delete(:user_id); @current_user=nil.

当然,这是过于简单化了,但是在您继续学习时值得牢记这一点。