在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类。