在请求之间共享的Sinatra路由中定义的全局变量



假设我有:

get '/' do
 $random = Random.rand()
 response.body = $random
end

如果我每秒有数千个请求来到/,$random会被共享并在上下文之外"泄漏"吗?或者它会像get块的"局部"变量一样?

我想如果它是在get '/' do上下文之外定义的,它确实会被共享,但我想知道ruby中是否有一个我不知道的机制

Sinatra README中关于作用域的这部分内容总是很有帮助的,但是如果你只需要在请求中保存变量,那么我认为有三种主要的方法可以做到这一点,关键是过滤器

前块

before do
  @my_log = []
end
get "/" do
  @my_log << "hello"
  @my_log << "world"
  @my_log.inspect
end
get "/something-else" do
  @my_log << "is visible here too"
end
# => output is ["hello", "world"]

@my_log将在请求结束时超出作用域,并在下一个请求开始时重新初始化。它可以通过任何路由访问,因此,如果您使用pass将其传递到另一条路由,这将是其他块可以看到之前路由块设置的唯一时间。

使用设置帮助器

set :mylog, []

然后同上,将@my_log替换为settings.my_log。如果没有before块重新初始化,那么@my_log的内容将在请求之间持久化。

使用像Redis这样的设置帮助器

# I always do this within a config block as then it's only initialised once
config do
  uri = URI.parse(ENV["URL_TO_REDIS"])
  set :redis, Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end

现在redis实例通过settings.redis可用。没有必要担心变量范围(我使用它的本地),只是直接推到Redis。你得到了两个世界的好处,但如果你想,你可以这样做:

before do
  @my_log = []
end
get "/" do
  @my_log << "hello"
  @my_log << "world"
  "Hello, World"
end
after do
  settings.redis.set "some_key", @my_log
  settings.redis.expire "some_key", 600 # or whatever
end

除了一些非常特殊的例外(例如正则表达式匹配相关的全局变量),全局变量与进程中的所有内容共享—没有作用域。

最新更新