Sinatra的通用设置

我在Sinatra有一个class级,我设置了一些设置(来自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 

但是,Resolver类不能这样做:解析器:Class的未定义方法`config’。

也许我的范围有误,或者我应该使用Sinatra :: Application?

当你从Sinatra::Baseinheritance一个类时,你正在制作一个Sinatra应用程序。 每个应用程序都有自己的 settings对象。 如果您想跨应用程序共享设置,您有一些选择:

  1. 合并应用程序。
  2. 使设置更易于全局访问。
  3. inheritance(见下面的编辑)

合并它们很容易(除非有一些我们不知道的特殊原因),你基本上把它们放在同一个类中。

为了使设置更易于全局访问,我将执行以下操作:

a)将整个应用程序包装在一个模块中以命名它。
b)将要使用的设置放在可通过“getter”方法访问的类实例变量中。

例如

 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 

如果你有一些非常小的应用程序,这很好,但如果你使用多个应用程序,那么你会想要分开一些东西。 我倾向于组织应用程序的方式是删除除了requirerun之外的任何东西的rackup文件(通常是config.ru )中的所有内容。 我把中间件和应用程序设置放在另一个文件中,通常是app/config.rb所以我知道它是来自config.ru的东西。 然后每个应用程序都有自己的文件(例如app/app.rbapp/secondary.rb

 # app/config.rb require "app" require "secondary" module MyNamespace # set up your getters… eg 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 

这种设置有很多好处 - 它更容易测试; 组织起来比较容易; 您可以更轻松地移动应用程序。 但YMMV一如既往。


我还应该补充一点,因为我不能理解,也可以使用inheritance,例如:

 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 

设置,路由,帮助程序,filter都是inheritance的,因此如果您在祖先应用程序中配置某些内容,它将在inheritance者中可用。 有时这样做会更好,可能是当设置只是Sinatra应用程序的“全局”或者你想创建可重用的应用程序和控制器时。 其他时候,您需要可以在模型,库等中使用的设置,然后我首先给出的更全局的解决方案将是最好的。