为什么Rails在用户会话之间共享代码?

时间:2015-08-20 21:48:27

标签: ruby-on-rails ruby-on-rails-4

当用户尝试登录我们的Rails应用程序时,我会联系第三方ICAM服务器,该服务器返回有关用户的一些信息(如果他存在于ICAM服务器中)。我收到一个带有用户名,电子邮件等的哈希...(我们的环境配置方式是ICAM服务器可以根据工作站凭据检测到试图登录的人的身份)。

我们在自定义宝石中完成所有这些工作。在登录过程中,我尝试缓存ICAM服务器返回的信息,因此我不必再次与ICAM服务器通信。天真地,我有一些基本上做过的代码:

module Foo
  def self.store_icam_data(data)
    @icam_data = data
  end

  def self.icam_data
    @icam_data || {}
  end
end

我刚刚发现两个用户登录系统时出现问题。当用户A登录时,@icam_data设置了他的信息。当用户B登录时,@icam_data设置了他的信息。用户A下次发出请求时,@icam_data内有用户B的信息,而不是用户A!

我不希望这个模块中的变量在线程/会话之间共享。它有效地使系统的所有当前用户成为登录的最后一个用户...一个非常粗糙的错误。

有人可以解释为什么这个@icam_data变量会在会话中共享吗?我期待数据/代码比显然更加孤立。

1 个答案:

答案 0 :(得分:2)

只有两种方法可以在请求之间共享数据:数据库(RDBMS,Redis等)和session对象(控制器内部)。任何其他改变并在请求结束时存活的数据都是副作用,应该避免。

您的类变量被保存到属于特定应用服务器进程的内存(RAM)区域(例如Unicorn工作进程)。单个进程自然会为很多请求提供服务,因为在每个请求上杀死和重启Rails都是低效的。

所以它不是" Rails共享代码"它的Web应用服务器在它所服务的所有请求中共享其内存区域。

如果要将少量数据绑定到当前用户,请使用session:

# save
session[:icam_data] = MyICAMModule.get_icam_data

# retain
MyICAMModule.set_icam_data(session[:icam_data])

session中提供了有关{{1}}的更多信息。

如果您有大量数据 - 请使用数据库。