在Sinatra(Ruby)中,如何在应用程序生命周期中创建仅赋值一次的全局变量?

arr*_*rac 28 ruby web-applications sinatra

在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!
Run Code Online (Sandbox Code Playgroud)

这导致了

nil
2
Run Code Online (Sandbox Code Playgroud)

在终端和,2浏览器中.

如果我尝试@a = 1输入initialize方法,我会收到错误WebApp.run!.

我觉得我错过了一些东西,因为如果我不能拥有全局变量,那么如何在应用程序实例化期间加载大数据呢?

before do 似乎每次有来自客户端的请求时都会调用它.

The*_*heo 38

class WebApp < Sinatra::Base
  configure do
    set :my_config_property, 'hello world'
  end

  get '/' do
    "#{settings.my_config_property}"
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,如果您使用Shotgun或其他一些在每个请求上重新加载代码的Rack runner工具,则每次都会重新创建该值,并且它看起来好像不会只分配一次.在生产模式下运行以禁用重新加载,您将看到它仅在第一个请求时分配(例如,您可以执行此操作rackup --env production config.ru).

  • 这非常有帮助.只是想补充一点,如果你想稍后改变设置,你需要使用常规赋值,例如:`def'/ change' {settings.my_config_property ='goodbye world'}` (3认同)

Mik*_*e R 5

我遇到了类似的问题,我试图@a使用该initialize方法初始化实例变量,但每次都会收到异常:

class MyApp < Sinatra::Application

    def initialize
        @a = 1
    end

    get '/' do
        puts @a
        'inside get'
    end
end
Run Code Online (Sandbox Code Playgroud)

我最终决定研究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
Run Code Online (Sandbox Code Playgroud)

看起来它确实进行了一些必要的引导,我需要致电super()

    def initialize
        super()
        @a = 1
    end
Run Code Online (Sandbox Code Playgroud)

这似乎解决了我的问题,一切正常。