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

Posted

技术标签:

【中文标题】在 Sinatra 和 Rails 之间共享 Yaml 配置文件【英文标题】:Sharing Yaml config files between Sinatra and Rails 【发布时间】:2013-08-19 18:43:24 【问题描述】:

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

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

是否有一种标准方法可以获取安装了我的 Sinatra 应用程序的主 Rack 应用程序的根目录?

【问题讨论】:

【参考方案1】:

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

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

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

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

ln -s path_to_rails_file.yaml path_to_sinatra_file.yaml

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

【讨论】:

【参考方案2】:

如果您通过在 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 模块都会检查环境哈希值。【参考方案3】:

如果您通过将 Sinatra 应用程序添加为中间件将其包含在 Rails 应用程序中,那么您可以在应用程序中添加一个构造函数来配置它。 Sinatra 有一个initialize method,它遵循通用的 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 应用程序,您可以在 config.ru 中使用普通的 use 执行类似的操作。如果您在需要 Rails 应用程序的行之后添加 use 行,您仍然可以使用 Rails.root 变量。

【讨论】:

以上是关于在 Sinatra 和 Rails 之间共享 Yaml 配置文件的主要内容,如果未能解决你的问题,请参考以下文章

Sinatra 与 Rails

Sinatra 应用程序作为机架中间件 TimeOut Rails 3

与Sinatra一起设计

将带有 Sinatra 2.0.0beta2 的 Rails 5 应用程序部署到 Amazon Linux AMI 时出错

在 Rails 和 Spring MVC 之间共享会话

Rails:在模型之间共享枚举声明值