在请求之间共享Sinatra路由内定义的全局变量吗? [英] Is a global variable defined inside a Sinatra route shared between requests?

查看:64
本文介绍了在请求之间共享Sinatra路由内定义的全局变量吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有:

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

如果我有数千个请求每秒到达/,$ random是否将被共享并在上下文之外泄漏,或者它像get块的 local变量一样起作用?

If I have thousands of requests per second coming to /, will the $random be shared and 'leak' outside the context or will it act like a 'local' variable to the get block?

我想如果它是在 get'/'do 上下文之外定义的,则确实可以共享,但是我想知道是否有我不知道的$红宝石机械师。

I imagine if it was defined outside of the context of get '/' do it would indeed be shared but I wonder if there's a mechanic to $ in ruby that I'm not aware of.

推荐答案

Sinatra自述文件中有关范围的这一部分对于阅读始终很有帮助,但是如果您只需要为请求保留变量,那么我认为那里我建议您采用以下3种主要方法,而真正的关键是过滤器

This part of the Sinatra README about scope is always helpful to read but if you only need the variable to persist for the request then I think there are 3 main ways I'd suggest going about this, and really the key is a filter

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 将其传递到另一条路线,这将是其他块只能看到的内容由先前的路线封锁。

@my_log will go out of scope at the end of the request and be re-initialised at the beginning of the next one. It will be accessible by any route, so if for example you used pass to pass it on to another route that would be the only time the other blocks could see what had been set by the prior route block.

set :mylog, []

然后与上述相同,只需替换 @my_log 使用 settings.my_log 。如果不将之前的$code>块重新初始化,则 @my_log 的内容将在请求中保持不变。

Then same as above, just replace @my_log with settings.my_log. Without the before block reinitialising it then the contents of @my_log would be persisted across requests.

# 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

现在,可通过 settings.redis 使用redis实例。无需担心可变范围(我将使用本地变量),只需直接推送到Redis。然后,您将两全其美,但是如果您愿意,可以这样做:

Now the redis instance is available via settings.redis. No need to worry about variable scope (I'd use locals with it), just push straight to Redis. You get the best of both worlds then, but if you want you could do:

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

这篇关于在请求之间共享Sinatra路由内定义的全局变量吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆