2

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

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

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

在这一点上,我只看到一种解决方法。Rails 应用程序必须在 application.rb 中配置 gem,以便在运行任何初始化程序之前配置 gem。

有人看到我缺少的东西吗?有没有办法让 gem 在初始化程序被处理之后(但在 Rails 开始完成启动过程之前)立即做一些工作?如果没有,Rails 似乎有另一个钩子会在处理完初始化程序后立即触发。

4

1 回答 1

3

感谢@Raffael 建议的链接,我能够想出一个解决方法。以防其他人遇到类似情况,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

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

于 2015-12-28T20:13:29.813 回答