Подтвердить что ты не робот

В 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 Кажется, вызывается каждый раз, когда есть запрос с клиентской стороны.

4b9b3361

Ответ 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 в представлениях и других загруженных файлах.