Как в Синатре (Ruby) создавать глобальные переменные, которым присваиваются значения только один раз за время существования приложения? - PullRequest
28 голосов
/ 24 декабря 2010

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

Ответы [ 4 ]

38 голосов
/ 24 декабря 2010
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).

5 голосов
/ 08 марта 2016

Я столкнулся с подобной проблемой, я пытался инициализировать переменную экземпляра @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

Это, казалось, решило мою проблему, и все работало какожидается.

1 голос
/ 09 июня 2014

Другой вариант:

helpers do

  def a
   a ||= 1
  end

end
0 голосов
/ 24 декабря 2010

Вы можете использовать OpenStruct.

require 'rubygems'
require 'sinatra'
require 'ostruct'

configure do
  Struct = OpenStruct.new(
    :foo => 'bar'
  )
end

get '/' do
  "#{Struct.foo}" # => bar
end

Вы даже можете использовать класс Struct в представлениях и других загруженных файлах.

...