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



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

在控制器的上下文中使用局部变量或实例变量之间是否有任何性能差异?

我不明白为什么 rails 在脚手架生成的 api 应用程序中的创建和索引方法中使用实例变量,如果变量没有重用

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

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

是否有任何性能差异?还是存在材料性能差异?我不知道第一个问题的答案。我想,第二个问题的答案是否定的,除非你以难以想象的规模这样做。即便如此,也很难想象。

顺便说一句,你可以做:

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

在您的示例中,不需要变量,无论是user还是@user

词法变量和实例变量的工作方式存在非常明显的实际差异:

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

在考虑轨道配置重点的约定时,这可能非常有用。控制器 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 回收,而实例变量将保留在对象中。不过,这很少是一个问题。

性能差异可以忽略不计。

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

另一个准则是"为测试而设计"。如果使用实例变量,则测试可以使用assigns(:user)检查它。该规则胜过"最弱的结构"规则。因此,请使用实例变量,并编写大量自动化测试!

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

谈到性能,我认为不会有太大差异,至少会有一些明显的东西。

并作为评论:

"实例变量在持有它的对象的生命周期内继续存在。局部变量仅存在于单个方法、块或模块主体中。

最新更新