在Rails API中使用局部变量或实例变量有什么区别?

时间:2018-06-07 16:17:36

标签: ruby-on-rails

在一个常见的应用程序中,我们使用实例变量,以便我们可以在视图中访问它们。但是在Rails api应用程序中需要什么呢?

使用本地变量或实例变量在Controllers的这个上下文中是否有任何性能差异?

我不明白为什么rails在由scaffold生成的api应用程序中的create和index方法中使用实例变量,如果该变量未被重用

def show
    user = User.find(params[:id])
    render json: UserSerializer.new(user)
 end


def show
    @user = User.find(params[:id])
    render json: UserSerializer.new(@user)
end

4 个答案:

答案 0 :(得分:4)

在这个确切的例子中,没有功能差异。

是否有任何性能差异?或者材料性能差异?我不知道第一个问题的答案。我想,第二个问题的答案是' no'除非你以一种难以想象的大规模做到这一点。即便如此,也很难想象。

顺便说一下,你可以这样做:

def show
  render json: UserSerializer.new(User.find(params[:id]))
end

在您的示例中,不需要变量user@user

答案 1 :(得分:4)

词汇和实例变量的工作方式有一个非常明显的实际区别:

class Thing
  def initialize
    @ivar = "Hello World"
  end
  def foo
    @ivar
  end
end

> Thing.new.foo
=> "Hello World"

由于实例变量附加到实例,因此它们可以在对象的方法之间共享,而不会像回调通常使用的那样传递值:

class API::V1::ThingsController < ::ApiController
  before_action :set_thing, except: [:create, :index]

  def show
    respond_with @thing
  end

  # ...

  private

    def set_thing
      @thing = Thing.find(params[:id])
    end
end

在考虑关于rails的配置焦点的约定时,这非常有用。通过视图上下文,视图中也提供了控制器IVAR。

另一方面,词法变量只存在于定义的词法范围(方法,块,proc或lambda)中:

class Thing
  def initialize
    lex = "Hello World"
  end
  def foo
    lex
  end
end

> Thing.new.foo
NameError: undefined local variable or method `lex' for #<Thing:0x007f87068b5968>

当您需要具有局部范围的短期变量时,它们更可取。 Rails也有locals,它实际上是一个哈希,你可以在渲染时填充不应该与词汇变量的Ruby概念混淆的东西。 Rails在视图上下文中使用method_missing来代理本地哈希。

性能差异很可能是极其可信的,因为两者都只是绑定到范围的变量 - 对象或方法/块。当范围关闭(方法完成)时,词法变量将由GC回收,尽管实例变量将与对象保持一致。这很少是一个问题。

答案 2 :(得分:2)

性能差异可以忽略不计。

但是有两个相互竞争的指导方针在起作用。一个是&#34;始终使用最薄弱的结构。&#34;不要使用双&#34;引号&#34;如果你可以使用单一&#39;引用&#39;。如果可以使用String #index,请不要使用正则表达式。如果可以使用局部变量,请不要使用实例变量。

另一个指南是&#34;测试设计。&#34;如果使用实例变量,则测试可以使用assigns(:user)进行检查。这条规则胜过最糟糕的建筑&#34;规则。所以使用实例变量,并编写大量自动化测试!

答案 3 :(得分:1)

在该示例中谈论功能没有区别。但是创建一个实例变量就是让以后可以访问该变量,可能是在视图上或在另一种方法中,在这种情况下,谈论api(你没有视图),如果你没有计划例如,在该控制器内的另一个方法中使用@user,你不需要创建它,只需要一个局部变量,它就足够了。

谈论表现,我不认为会有太多差异,至少有些明显。

作为评论:

&#34;实例变量在持有它的对象的生命周期中继续存在。局部变量仅存在于单个方法,块或模块体中。&#34;