I'm building a Rails Engine which uses OmniAuth. OmniAuth needs to add some middleware to the Rails middleware stack and a suggested way to do this, according to OmniAuth, is to do it in an initializer. I've tried it, and I'm successfully able to create an initializer inside the gem, which gets loaded when the Rails app starts. Now, I'm trying to add some configuration options to my gem and I would like the gem user to be able to create another initializer to configure the gem BEFORE before the gem's initializer does it's work.
What I have discovered is any initializers inside ALL Engines are loaded first. Then the initializers inside the Rails app are loaded next. I had hoped I would be able to name the initializers in such a way that I could control the load order, but Rails app initializers still process after the gem's initializers. This makes perfect sense to me, but it leaves me with a initializer load order problem. The Rails app will go last so by the time it's given a chance to configure the gem, the gem has already done it's work.
My next thought was to use the after_initialize
callback inside the engine's Railtie. In most situations this might work, but in this particular use case it doesn't help. By the time after_initialize
is called, the middleware stack is frozen and can't be changed (which makes it useless for code who's only purpose is to change the middleware stack).
At this point, I only see one workaround. The Rails app will have to configure the gem inside application.rb so it configure the gem before any initializers are run.
Does anyone see something I'm missing? Is there a way for the gem to do some work IMMEDIATELY after the initializers have been processed (but before Rails starts finalizing the boot process)? If not, it seems like it would be useful for Rails to have another hook that would fire as soon as the initializers are processed.
Thanks to the link suggested by @Raffael, I was able to come up with a workaround. In case anyone else runs into a similar situation, app_middleware
saved the day.
I was able to register the OmniAuth middleware using app_middleware via:
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
This helped resolve the initialization order I was hitting.