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

时间:2013-01-17 21:14:53

标签: ruby routing sinatra

说我有:

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

如果我每秒有数千个请求进入/,$ random会在上下文之外共享和“泄漏”,还是会像get块的“本地”变量一样?

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

2 个答案:

答案 0 :(得分:18)

This part of the Sinatra README about scope is always helpful to read但是如果您只需要变量来保留请求,那么我认为有三种主要方式我建议这样做,而且关键是filter

A block

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

现在可以通过settings.redis获得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

答案 1 :(得分:2)

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