在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在浏览器中。

如果我尝试在initialize方法中放置@a = 1 ,我在WebApp.run!收到错误WebApp.run! 线。

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

每次有来自客户端的请求时,似乎都会调用。

 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 )。

我遇到了类似的问题,我试图使用initialize方法初始化一个实例变量@a ,但每次都保持接收exception:

 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 

看起来它做了一些必要的bootstrapping,我需要调用super()

  def initialize super() @a = 1 end 

这似乎解决了我的问题,一切都按预期工作。

另外一个选项:

 helpers do def a a ||= 1 end end 

您可以使用OpenStruct。

 require 'rubygems' require 'sinatra' require 'ostruct' configure do Struct = OpenStruct.new( :foo => 'bar' ) end get '/' do "#{Struct.foo}" # => bar end 

您甚至可以在视图和其他加载的文件中使用Struct类。