6

Say I've got:

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

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?

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.

4

2 回答 2

19

Sinatra 自述文件中关于范围的这一部分总是有助于阅读,但如果您只需要变量来为请求保留,那么我认为有 3 种主要方法我建议解决这个问题,真正的关键是一个过滤器

一个前块

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_logsettings.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
于 2013-01-20T01:19:12.897 回答
3

除了一些非常具体的例外(例如正则表达式匹配相关的全局变量)之外,全局与进程中的所有内容共享 - 没有范围。

于 2013-01-17T22:24:41.717 回答