【问题标题】:Are instance variables necessary for Rails as API only?Rails 作为 API 是否需要实例变量?
【发布时间】:2020-06-15 08:44:26
【问题描述】:

实例变量在 Rails API 中扮演什么角色?我正在使用 Ruby on Rails 构建后端 API,并且正在关注 Michael Hartl 的 RoR 教程。他在 RoR 的模板引擎中使用了实例变量。但是,如果我只是简单地将 RoR 用作 API,我还需要实例变量吗?

下面是snippet from Michael Hartl's tutorial,介绍如何找到当前用户。

  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 has closed the browser before and persistent session exists
      user = User.find_by(id: user_id)
      if user&.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

我正在从一个分离的前端发出 Web 请求,@current_user 是否总是以 nil 开头?我可以简单地使用常规变量吗?

【问题讨论】:

  • 如果您没有任何视图并且实例变量未在类中的任何其他位置(或从此类继承的任何类)中使用,那么您可以将它们替换为局部变量。实例变量用于从类中的任何实例方法访问该变量,或将变量公开给视图文件。
  • @Mark 谢谢马克!如果您将其写为答案,我将很乐意接受!

标签: ruby-on-rails ruby


【解决方案1】:

正如@Mark 在问题中所写,如果您不在视图中访问实例变量,则可以只使用局部变量。

我正在从一个解耦的前端发出 Web 请求,@current_user 是否总是从零开始?我可以简单地使用常规变量吗?

您如何与前端沟通?我假设它确实请求 JSON?然后你需要将你的实例/局部变量暴露给你的 JSON。像这样的:

class UsersController < ApplicationController
  def show
    render json: { current_user: current_user }
  end

  private

  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&.authenticated?(cookies[:remember_token])
        log_in user
        @current_user ||= user
      end
    end
  end
end

另外我认为在你的教程的例子中,这个方法也被用来记忆当前用户并且不要再次获取它/再次登录。如果分开,可能会更清楚:

  def current_user
    @_current_user ||= fetch_current_user
  end

  def fetch_current_user
    if (user_id = session[:user_id])
      User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id]) # User has closed the browser before and persistent session exists
      user = User.find_by(id: user_id)
      if user&.authenticated?(cookies[:remember_token])
        log_in user
        user
      end
    end
  end

现在我们将当前用户存储在current_user 中,并且不要再次登录或从数据库(https://en.wikipedia.org/wiki/Memoization)中再次获取它。例如,如果您需要进行身份验证/授权检查,则需要多次访问 current_user。

class UsersController < ApplicationController
  before_action :check_user

  def show
    render json: { current_user: current_user }
  end

  private

  def check_user
    return unless current_user.admin?

    render json: {}, status: 404
  end
end

编辑

通常用于指示实例变量不直接使用而仅用于记忆的约定是以下划线作为前缀。

def current_user
  @_current_user ||= fetch_current_user
end

def fetch_current_user; end

Ruby 中的记忆是用||= 完成的,它的计算结果是@_current_user || @_current_user = fetch_current_user,所以@_current_user 只有在@_current_user 逻辑上为假时才被设置。因此,如果 a 已经设置,我们不需要再次获取它,只需使用存储在实例变量中的值即可。

【讨论】:

  • 哇很好的答案!是的,我用 JSON 发回数据
  • 添加了更多关于命名约定和 Ruby 中记忆化如何工作的上下文。
【解决方案2】:

如果您没有任何视图并且实例变量未在类中的任何其他位置(或从此类继承的任何类)中使用,则可以将它们替换为局部变量。

实例变量用于从类中的任何实例方法访问该变量,或将变量公开给视图文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 2013-05-02
    • 2011-08-16
    • 2017-12-22
    • 2011-12-14
    • 2011-03-05
    • 1970-01-01
    相关资源
    最近更新 更多