我在Sinatra有一个班级,我设置了一些设置(来自JSON,因为它发生了):
class Pavo < Sinatra::Base
configure :development do
set :config, JSON.parse(File.open(File.dirname(__FILE__) + "/pavo.configuration.development.json", "rb").read)
set :config_mtime, File.mtime(File.dirname(__FILE__) + "/pavo.configuration.development.json")
end
[...]
get '/' do
puts "whatever"
end
end
该类有一个模型,需要读取这些设置。
class Resolver < Sinatra::Base
def get_data(workpid)
url_str = settings.config['public']['BOOKS_DATA_SERVICE_URL'].gsub('${WORKPID}', workpid)
return Resolver.get_json(url_str)
end
[...]
end
然而,解析器类不能这样做:未定义的方法`config&#39;解析器:Class。
也许我的范围有误,或者我应该使用Sinatra :: Application?
答案 0 :(得分:3)
当你从Sinatra::Base
继承一个类时,你正在制作一个Sinatra应用程序。每个应用程序都获得自己的 settings
对象。如果您想跨应用程序共享设置,您有一些选择:
合并它们很容易(除非有一些我们不知道的特殊原因),你基本上把它们放在同一个类中。
为了使设置更易于全局访问,我将执行以下操作:
a)将整个应用程序包装在一个模块中以命名它 b)将要使用的设置放在可通过“getter”方法访问的类实例变量中。
e.g。
module MyNamespace
def self.global_settings
@gs ||= # load your settings
end
class App < Sinatra::Base
configure do
set :something_from_the_global, MyNamespace.global_settings.something
end
end
class SecondaryApp < Sinatra::Base
helpers do
def another_method
MyNamespace.global_settings.something_else # available anywhere
end
end
configure do # they're also available here, since you set them up before the app
set :something_from_the_global, MyNamespace.global_settings.something
end
end
end
如果您有一些非常小的应用程序,这很好,但如果您使用多个应用程序,那么您将需要稍微分开一些。除了config.ru
和require
之外,我倾向于组织应用的方式是从除了run
和app/config.rb
之外的任何内容的rackup文件(通常是config.ru
)中删除所有内容。我将中间件和应用程序设置放在另一个文件中,通常是app/app.rb
,所以我知道它来自app/secondary.rb
。然后,每个应用程序都会获得自己的文件(例如# app/config.rb
require "app"
require "secondary"
module MyNamespace
# set up your getters… e.g.
def self.global_settings
@gs ||= # load your settings
end
def self.app
Rack::Builder.app do
# …and middleware here
use SecondaryApp
run App
end
end
end
# config.ru
require 'rubygems'
require 'bundler'
Bundler.require
root = File.expand_path File.dirname(__FILE__)
require File.join( root , "./app/config.rb" )
map "/" do
run MyNamespace.app
end
,require 'sinatra/base'
module MyNamespace
class Controller < Sinatra::Base
configure :development do
set :config, "some JSON"
set :mtime, Time.now.to_s
end
end
class App1 < Controller
get "/app1" do
"in App1 config: #{settings.config} mtime: #{settings.mtime}"
end
end
class App2 < Controller
get "/app2" do
"in App2 with config: #{settings. config} mtime: #{settings.mtime}"
end
end
end
)
{{1}}
这种设置有很多好处 - 它更容易测试;它更容易组织;你可以更容易地移动应用程序。但YMMV一如既往。
我还应该补充一点,因为我不能理解,也可以使用继承,例如:
{{1}}
设置,路由,帮助程序,过滤器都是继承的,因此如果您在祖先应用程序中配置某些内容,它将在继承者中可用。有时这样做会更好,可能是当设置只是Sinatra应用程序的“全局”或者你想创建可重用的应用程序和控制器时。其他时候,你需要可以在模型,库等中使用的设置,然后我首先给出的更全局的解决方案是最好的。