В Sinatra (Ruby), как мне создать глобальные переменные, которым присваиваются значения только один раз в жизни приложения?
В Sinatra я не могу создать глобальные переменные, которым присваиваются значения только один раз в жизни приложения. Я что-то упускаю? Мой упрощенный код выглядит следующим образом:
require 'rubygems' if RUBY_VERSION < "1.9"
require 'sinatra/base'
class WebApp < Sinatra::Base
@a = 1
before do
@b = 2
end
get '/' do
puts @a, @b
"#{@a}, #{@b}"
end
end
WebApp.run!
В результате получается
nil
2
в терминале и ,2
в браузере.
Если я попытаюсь поместить @a = 1
в метод initialize
, я получаю сообщение об ошибке в строке WebApp.run!
.
Я чувствую, что у меня что-то не хватает, потому что, если у меня не могут быть глобальные переменные, то как я могу загружать большие данные во время создания приложения?
before do
Кажется, вызывается каждый раз, когда есть запрос с клиентской стороны.
Ответы
Ответ 1
class WebApp < Sinatra::Base
configure do
set :my_config_property, 'hello world'
end
get '/' do
"#{settings.my_config_property}"
end
end
Остерегайтесь того, что если вы используете Shotgun или какой-либо другой инструмент Rack runner, который перезагружает код для каждого запроса, значение будет каждый раз воссоздаваться, и оно будет выглядеть так, как если бы оно не было назначено только один раз. Запустите в режиме производства, чтобы отключить перезагрузку, и вы увидите, что он назначен только по первому запросу (вы можете сделать это, например, с помощью rackup --env production config.ru
).
Ответ 2
У меня возникла аналогичная проблема, я пытался инициализировать переменную экземпляра @a
с помощью метода initialize
, но каждый раз получал исключение:
class MyApp < Sinatra::Application
def initialize
@a = 1
end
get '/' do
puts @a
'inside get'
end
end
Наконец-то я решил изучить код Sinatra для инициализации:
# File 'lib/sinatra/base.rb', line 877
def initialize(app = nil)
super()
@app = app
@template_cache = Tilt::Cache.new
yield self if block_given?
end
Похоже, он выполняет некоторую необходимую загрузку, и мне нужно было позвонить super()
.
def initialize
super()
@a = 1
end
Это, казалось, исправить мою проблему, и все сработало, как ожидалось.
Ответ 3
Другая опция:
helpers do
def a
a ||= 1
end
end
Ответ 4
Вы можете использовать OpenStruct.
require 'rubygems'
require 'sinatra'
require 'ostruct'
configure do
Struct = OpenStruct.new(
:foo => 'bar'
)
end
get '/' do
"#{Struct.foo}" # => bar
end
Вы даже можете использовать класс Struct в представлениях и других загруженных файлах.