在Sinatra请求之间共享Ruby变量

时间:2014-02-21 21:02:35

标签: html ruby rest web sinatra

我正在尝试在sinatra中编写一个简单的问答游戏,我需要为所有用户提供可访问的公共对象(大厅状态,聊天消息等)。问题是Sinatra在每个请求和对象变为初始状态后重新加载代码。如何实现呢?

2 个答案:

答案 0 :(得分:10)

嗯,这个话题有点棘手。 Sinatra实际上没有重置服务器状态:

require 'sinatra'

GlobalState = {}
GlobalState[:some_counter] = 0

get '/' do
  response = "GlobalState[:some_counter]: #{GlobalState[:some_counter]}"
  GlobalState[:some_counter] += 1
  response
end

此代码没有错:如果您运行它并转到http://localhost:4567,您会看到GlobalState[:some_counter]按预期增加。

但是因为以下原因而不鼓励,主要与应用程序的Web性质有关:

  1. 由于数据存储在Ruby对象中,因此如果停止服务器,则会丢失数据。但是,如果你不需要持久性数据,这不是问题
  2. 当您运行Web应用程序时,通常会同时拥有应用程序实例,以便同时处理多个请求。有几种方法可以实现它:
    1. Forks:同一应用程序的多个进程。它们不共享内存,因此Ruby全局状态变量变得无用
    2. 线程:线程共享内存,因此您可以访问全局状态,但是您必须管理对同一个全局对象的并发访问,这会产生非常重要的后果。
  3. 您无法将数据与用户关联,反之亦然:这是因为HTTP不提供状态保留方法(它是stateless protocol)。要解决它,您需要:
    1. 客户端数据存储:cookies,HTML5本地存储......
    2. 服务器端数据存储:会话(实际上不是服务器端 ,至少需要将会话关联到相应的客户端,通常将会话ID存储到cookie中)
  4. 出于这些原因,Web应用程序数据管理并非易事。无论如何不要担心,你不必重新发明轮子;解决方案在手:

答案 1 :(得分:0)

没有某种类型的持久存储,没有办法做到这一点。您必须将信息存储在数据库或cookie中。