为什么在模块中使用实例变量而不是局部变量?

问题描述 投票:-1回答:2

我在Ruby on Rails应用程序中看到了这段代码:

module SessionsHelper
  def current_user
    @current_user ||= User.find_by id: session[:user_id]
  end

  ...
end

为什么在current_user方法中使用实例变量而不是局部变量?当我将其更改为局部变量时,一切都与使用实例变量相同。

我读到一个实例变量可以用在包含这个模块的许多其他类中。但在这种情况下,它们是用current_user方法定义的,用于存储用户的值@current_user。这在其他许多课程中如何使用?

ruby memoization
2个回答
0
投票

这大致意味着如果已经定义了@current_user作为全局请求/响应范围(Controller / View / Helpers)的实例变量,则将其用作current_user。否则,为其分配与会话中存储的id对应的用户执行的操作。

换句话说,这类似于:

def current_user
    if @current_user # this will be false in every hit, for the same request
        @current_user
    else
        User.find_by id: session[:user_id]
    end
end

这应该足够了。

但是,你可以在代码的其他部分再次使用current_user,让我们在控制器中说同样的请求。

这意味着,current_user将不得不再次击中DB(缓存除外)。如果可以的话,你想避免这种情况。那么,为什么不将用户存储在全局实例变量中呢?

从而:

def current_user
    if @current_user # this will be false for the first hit, true for every subsequent request
        @current_user 
    else
        @current_user = User.find_by id: session[:user_id]
    end
end

既然我们这样做,为什么不使用速记方法呢?

所以,最后:

def current_user
    @current_user ||= User.find_by id: session[:user_id]
end

答案是,您在同一请求/响应中执行此操作以进行可重用性抖动。


2
投票

@current_user || = User.find_by id:session [:user_id]

这里使用了一些Ruby快捷方式,所以让我们扩展为:

 if @current_user == nil
   @current_user = User.find_by id: session[:user_id]
 end

 return @current_user

太好了。但是这个数据库查找实际上可能需要很长时间(比如我们每次调用它都需要几十毫秒)。这可能不会感觉很长时间,但它最终会加起来--Rails应用程序会调用当前用户(仅请求一次与几十次也会减少数据库服务器上的负载)。 (没有任何类型的缓存ActiveRecord和Rails正在你背后做......

因此,我们将结果保存到我们以后的实例变量中。

因此,如果您在current_user方法中执行了类似的操作

if my_current_user
  my_current_user = User.find_by id: session[:user_id]
end

return my_current_user

这将始终进入if语句,始终执行查找,将答案放在本地并返回它。下次它不知道它已经查找了,所以将再次进行相同的数据库查询,获得结果等等。所以它可能会工作,但它会比在这里使用实例变量慢。

当然,有一个缺点。 Ruby中的模块可以导入到类中 - 模块中的方法成为类的方法。所以是的,现在您已经为导入模块的所有类创建了一个实例变量。这是......可能不完全友好(如果其他一些模块也使用该名称会怎么样?),但是ehhhhhhhhhhh ....在一个小的初学者代码库中它并不重要。

© www.soinside.com 2019 - 2024. All rights reserved.