6

私が持っていると言う:

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

/に毎秒数千のリクエストが来る場合、$ randomは共有され、コンテキスト外で「リーク」しますか、それともgetブロックに対して「ローカル」変数のように機能しますか?

それが文脈の外で定義されたとしたら、get '/' doそれは確かに共有されるだろうと思いますが、私が知らないルビーの$のメカニズムがあるのではないかと思います。

4

2 に答える 2

19

スコープに関するSinatraREADMEのこの部分は、常に読むのに役立ちますが、要求に対して永続化する変数のみが必要な場合は、これについて行うことをお勧めする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_logますsettings.my_logbeforeブロックを再初期化しないと、の内容は@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 に答える