在一个常见的应用程序中,我们使用实例变量,以便我们可以在视图中访问它们。但是在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
答案 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;