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

Ruby on rails 在Sinatra和Rails之间共享Yaml配置文件,ruby-on-rails,ruby,sinatra,Ruby On Rails,Ruby,Sinatra,我正在将现有Rails应用程序中的Sinatra应用程序提取到一个gem中,以便在同一Rails应用程序中重用。我想在它的当前位置Rails.root/config(标准点)保留一个配置文件,但仍然从Sinatra应用程序使用它。我怎样才能做到干净呢 目前,Sinatra应用程序的设置。root指向供应商目录深处的某个路径。我想这是因为Sinatra应用程序是一块宝石。这意味着我必须猜出许多目录才能找到Rails应用程序的根目录 是否有一种标准方法来获取安装我的Sinatra应用程序的主机架应用

我正在将现有Rails应用程序中的Sinatra应用程序提取到一个gem中,以便在同一Rails应用程序中重用。我想在它的当前位置
Rails.root/config
(标准点)保留一个配置文件,但仍然从Sinatra应用程序使用它。我怎样才能做到干净呢

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


是否有一种标准方法来获取安装我的Sinatra应用程序的主机架应用程序的根目录?

没有干净的方法,因为这些应用程序是完全不同的堆栈

您可以使用服务器的操作系统对Sinatra代码进行欺骗,这是我们所做的

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

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

ln -s path_to_rails_file.yaml path_to_sinatra_file.yaml

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

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

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

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

def self.config_from_file(filename)
  data = YAML.load_file(filename)
  set :foo, data['foo']
  # set other vars from Yaml as appropriate
end
# 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'
现在,您的路线中将提供
settings.foo

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

def self.config_from_file(filename)
  data = YAML.load_file(filename)
  set :foo, data['foo']
  # set other vars from Yaml as appropriate
end
# 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有一个遵循通用机架中间件接口的应用程序,第一个参数是将请求传递给的应用程序。通过在子类中重写它,您可以执行任何需要的配置

例如,在您的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应用程序,可以在
config.ru
中使用普通
use
执行类似的操作。如果在需要Rails应用程序的行之后添加
use
行,您仍然可以使用
Rails.root
变量。

我将此与使用中间件结合使用,在传递调用之前设置一些环境哈希值。我的每个Sinatra模块都会检查环境哈希值。