控制 Rails 初始化程序加载顺序(可能需要新的 Rails 初始化挂钩)

Controlling Rails Initializer Load Order (Possible Need for new Rails Initialization Hook)

我正在构建一个使用 OmniAuth 的 Rails 引擎。 OmniAuth 需要向 Rails 中间件堆栈添加一些中间件,根据 OmniAuth 的建议,建议的方法是在初始化程序中执行此操作。我试过了,我成功地在 gem 中创建了一个初始值设定项,它在 Rails 应用程序启动时加载。现在,我正在尝试向我的 gem 添加一些配置选项,我希望 gem 用户能够创建另一个初始化程序来在 gem 之前配置 gem =] 的初始化程序可以正常工作。

我发现所有引擎中的任何初始值设定项都首先加载。然后接下来加载 Rails 应用程序中的初始化程序。我曾希望我能够以可以控制加载顺序的方式命名初始化程序,但 Rails 应用程序初始化程序仍在 gem 的初始化程序之后处理。这对我来说非常有意义,但它给我留下了初始化程序加载顺序问题。 Rails 应用程序将运行到最后,因此当它有机会配置 gem 时,gem 已经完成了它的工作。

我的下一个想法是在引擎的 Railtie 中使用 after_initialize 回调。在大多数情况下这可能有效,但在这个特定用例中它没有帮助。调用 after_initialize 时,中间件堆栈已冻结且无法更改(这使得它对那些唯一目的是更改中间件堆栈的代码毫无用处)。

此时,我只看到一种解决方法。 Rails 应用程序必须在 application.rb 中配置 gem,因此它会在任何初始化器 运行.

之前配置 gem

有人看到我遗漏了什么吗?有没有办法让 gem 在初始化器处理后立即做一些工作(但在 Rails 开始完成引导过程之前)?如果没有,似乎 Rails 有另一个钩子会很有用,该钩子会在处理初始化器时立即触发。

感谢@Raffael 建议的 link,我能够想出一个解决方法。以防其他人遇到类似情况,app_middleware 挽救了这一天。

我能够使用 app_middleware 通过以下方式注册 OmniAuth 中间件:

class Railtie < Rails::Railtie
  config.before_initialize do
    setup_proc = lambda do |env|
       options = {
        issuer: "foo",
        # Other options ...
      }
      env['omniauth.strategy'].options.merge!(options)
    end

    config.app_middleware.use OmniAuth::Builder do
      provider :saml, :setup => setup_proc
    end
  end
end

这有助于解决我遇到的初始化顺序问题。