ruby-on-railsrackrails-engines

How to load gem's Railites only after all config/initializers load?


I have a gem which conditionally loads RailsWarden::Manager, based on a flag in the config/initializers/mygem.rb file:

module Mygem
  class Railtie < Rails::Railtie
    initializer "mygem_engine.initialize_warden" do |app|
      if Mygem.use_warden_middleware?
        app.config.middleware.use RailsWarden::Manager do |manager|
          # Config for RailsWarden::Manager
        end
      end
    end
  end
end

This worked fine in some consumers, but in others the use_warden_middleware? gets called before the corresponding line in the config/initializers/mygem.rb gets loaded, to set the value to false (default is true).

This Railtie is loaded in the host apps config/application.rb with the line require "mygem/railtie" after the Bundler.require(*Rails.groups) line.

The only solution I've found is to add a line before that to require the initializer so that it loads first:

require_relative "initializers/mygem"
require "mygem/railtie"

However, I would rather not make the gem's consumers have to include both of these lines. Is there any way, in my gem to say "wait till the config is loaded before the mygem_engine.initialize_warden runs"?

I have tried adding a config.after_initialize block in the Railtie, but it seems then that runs too late for the middleware to be added correctly.


Solution

  • You can use :before or :after option on initializer to specify when this particular block should be run:

    initializer "mygem.warden", after: :load_config_initializers do
      # TODO: code here
    end
    

    load_config_initializers: Loads all Ruby files from config/initializers in the application, railties, and engines. The files in this directory can be used to hold configuration settings that should be made after all of the frameworks are loaded.

    https://guides.rubyonrails.org/configuring.html#initializers