在Sinatra和Rails之间共享Yaml配置文件



我正在从现有的Rails应用程序中提取一个Sinatra应用程序,将其提取到一个gem中,以便在同一个Rails应用程序内重用。我想在Rails.root/config(标准点)的当前位置留下一个配置文件,但仍然使用Sinatra应用程序中的配置文件。我该如何做到干净?

目前,Sinatra应用程序的settings.root指向供应商目录深处的某个路径。我想这是因为Sinatra应用程序是一颗宝石。这意味着我必须猜测出许多目录才能找到Rails应用程序的根目录。

有没有一种标准的方法来获取安装Sinatra应用程序的主Rack应用程序的根目录?

没有clean方法,因为应用程序是完全不同的堆栈。

您可以使用服务器的操作系统在Sinatra代码上玩把戏,这是我们所做的

如果您使用的是Linux或Mac操作系统,请为您的Sinatra应用程序创建一个指向Rails配置文件的软链接。您可以编写一个创建它的rakefile,并在安装代码时运行该脚本。

在操作系统级别,您希望使用:

ln -s path_to_rails_file.yaml path_to_sinatra_file.yaml

您甚至可以为Rails和Sinatra的YAML文件创建软链接,指向父目录或/etc/etc中的一个文件实例。不过,你会想在适当的地方添加一些自述文件,记录软链接的使用情况,或者你会在某个凌晨3点讨厌自己,因为你不记得为什么这么做了。

如果您通过在config/routes.rb中安装一个条目来包含Sinatra应用程序,则可以在mount调用之前通过调用其上的方法来配置它。

您在此处调用的任何方法都将在应用程序中的任何configure块之后运行,因此,如果您想做比设置单个变量更复杂的事情(使用Sinatra set命令),则需要添加一个可以从routes.rb调用的类方法。

例如,如果您想要一个包含条目foo的Yaml配置文件,那么在您的Sinatra应用程序中添加以下内容:

def self.config_from_file(filename)
  data = YAML.load_file(filename)
  set :foo, data['foo']
  # set other vars from Yaml as appropriate
end

现在settings.foo将在您的路线中可用。

在Rails config/routes.rb中,您需要添加以下内容:

# first configure your app
MyApp.config_from_file(File.join("#{Rails.root}/config", "foo_config.yaml"))
# now mount it at the appropriate url
mount MyApp.new => '/foo'

如果您要将您分离的Sinatra应用程序作为中间件添加到Rails应用程序中,那么您可以向应用程序添加一个构造函数来配置它。Sinatra有一个initialize方法,它遵循通用的Rack中间件接口,第一个参数是要向其传递请求的应用程序。通过在子类中重写它,您可以执行任何需要的配置。

例如,在您的Sinatra应用程序中:

def initialize(app, config_file)
  super(app)
  data = YAML.load_file(config_file)
  settings.foo = data['name']
end

为了使对settings.foo的调用正常工作,您需要在配置块中为foo设置一个默认值,因为initialize方法在类的实例范围内运行,并且不能访问set方法:

configure do
  set :foo, nil
end

现在,您可以在application.rb中添加中间件(或者在任何您想添加的地方),如下所示:

config.middleware.use MyApp, File.join(Rails.root, "config/foo_settings.yaml")

如果你想在Rails应用程序之外安装Sinatra应用程序,你可以用普通的useconfig.ru中做类似的事情。如果在需要Rails应用程序的行之后添加use行,则仍然可以使用Rails.root变量。

最新更新