Tim Santeford
Tim Santeford

Reputation: 28111

How do I change the load order of initializers in Rails?

I have an initializer that loads configuration settings from a yaml file. I need to use these settings in other initializers. The settings are not being seen by the initializers that need them. What I think is happening is the settings are getting loaded too late. How do I guaranty that my configuration initializer gets loaded first? Is it un-rails like to have initializers depend on another?

Thanks!

Upvotes: 73

Views: 31466

Answers (6)

Benjamin Boccara
Benjamin Boccara

Reputation: 96

I just released a gem named ordered_initializers that allows you to set the order in which you want your initializers to load, independently of their name, using a yml file.

Hope it could help. Feedbacks are welcome :)

Upvotes: 0

Shrutee
Shrutee

Reputation: 1915

I found that the easiest way is to use config/boot.rb. Any settings required in prior for another initialiser to load can be loaded in config/boot.rb.

I was getting empty value for SysconfigIngestion.config['google_oauth'] when called inside my initializer config/initializers/omniauth.rb. Shifting it to boot.rb did the job.

config/boot.rb

require 'rubygems'
...

require File.expand_path('config/initializers/sysconfig_loader.rb')
SysconfigLoader.init

require File.expand_path('config/initializers/cipher.rb')

if ENV['DOCKER'] == 'true'
    oauth = SysconfigLoader.config['google_oauth']
    ENV['GOOGLE_CLIENT_ID'] ||= oauth['client_id']
    ENV['GOOGLE_CLIENT_SECRET'] ||= Cipher.decrypt oauth['secret']
end

config/initializers/omniauth.rb

Rails.application.config.middleware.use OmniAuth::Builder do
  ## Following did not work
  ## SysconfigLoader.init
  ## oauth = SysconfigLoader.config['google_oauth']
  ## puts oauth['secret'].nil? # true

  ## But boot.rb successfully loaded the required values into ENV variables
  ENV['GOOGLE_CLIENT_SECRET'].nil? ? puts("Missing oauth secret!") : puts("Found oauth secret :)")

  provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], {}  
end

Application prints Found oauth secret :) on startup!!

Upvotes: 0

Peter J. Hart
Peter J. Hart

Reputation: 377

Use a require_relative to make sure one file is loaded first.

# aaa.rb
require_relative 'bbb'
# ... code using values from bbb.rb ...

Upvotes: 9

noomerikal
noomerikal

Reputation: 791

Even though the guide recommends prepending the initializer filenames with numbers, that does seem ugly. Another way is to utilize the provided initialization hooks. See http://guides.rubyonrails.org/configuring.html#initialization-events

E.g.

# application.rb

module YourApp
  class Application < Rails::Application
    config.before_initialize do
     # initialization code goes here
    end
  end
end

Upvotes: 33

Tyler Liu
Tyler Liu

Reputation: 20356

Put the configuration code in config/environment.rb file, right after the first require statement, such as:

# Load the rails application
require File.expand_path('../application', __FILE__)

# Load global configurations
CONFIG = Hashie::Mash.new YAML.load_file(Rails.root.join("config", "application.yml"))[Rails.env]

# Initialize the rails application
RailsSetup::Application.initialize!

Upvotes: 31

Julio Santos
Julio Santos

Reputation: 3895

Rename the initializer to 01_name.rb, that will force it to load alphabetically previously.

Edit

To quote the official Rails Guide for configuration (thanks zetetic for the tip):

If you have any ordering dependency in your initializers, you can control the load order by naming. For example, 01_critical.rb will be loaded before 02_normal.rb.

Upvotes: 102

Related Questions