开发者

In Sinatra(Ruby), how should I create global variables which are assigned values only once in the application lifetime?

开发者 https://www.devze.com 2023-01-31 21:22 出处:网络
In Sinatra, I\'m unable to create global variables which are assigned values only once in the application lifetime. Am I missing something? My simplified code looks like this:

In Sinatra, I'm unable to create global variables which are assigned values only once in the application lifetime. Am I missing something? My simplified code looks like this:

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!

This results in

nil
2

in the terminal and ,2 in the browser.

If I try to put @a = 1 in the initialize method, I'm getting an error in the WebApp.run! line.

I feel I'm missing something because if I can't have global variables, then how can I load large data during application instantiation?

before do seem开发者_如何学Pythons to get called every time there is a request from the client side.


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

  get '/' do
    "#{settings.my_config_property}"
  end
end

Beware that if you use Shotgun, or some other Rack runner tool that reloads the code on each request the value will be recreated each time and it will look as if it's not assigned only once. Run in production mode to disable reloading and you will see that it's only assigned on the first request (you can do this with for example rackup --env production config.ru).


I ran into a similar issue, I was trying to initialize an instance variable @a using the initialize method but kept receiving an exception every time:

class MyApp < Sinatra::Application

    def initialize
        @a = 1
    end

    get '/' do
        puts @a
        'inside get'
    end
end

I finally decided to look into the Sinatra code for initialize:

# 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

Looks like it does some necessary bootstrapping and I needed to call super().

    def initialize
        super()
        @a = 1
    end

This seemed to fix my issue and everything worked as expected.


Another option:

helpers do

  def a
   a ||= 1
  end

end


Building on Theo's accepted solution, it is also possible to do:

class App < Sinatra::Application

  set :blabla, ''

  namespace '/b' do
    get '/baby' do
      # do something where bouh is assigned a value
      settings.blabla = 'bouh'
    end
  end
 
  namespace '/z'
    get '/human' do
      # settings.blabla is available here with newly assigned value
    end
  end
end


You could use OpenStruct.

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

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

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

You can even use the Struct class in views and other loaded files.

0

精彩评论

暂无评论...
验证码 换一张
取 消