Mario Uher
Mario Uher

Reputation: 12397

Better way to organize Rails initializers

in my current Rails project I ended up with a lot of environment-specific initializers, for example my carrierwave.rb:

For development I use something like:

CarrierWave.configure do |config|
  config.cache_dir = Rails.root.join('tmp', 'carrierwave')
  config.storage = :file
end

For production I use S3 through fog:

CarrierWave.configure do |config|
  config.cache_dir = Rails.root.join('tmp', 'carrierwave')
  config.storage = :fog

  config.fog_public  = false
  config.fog_credentials = {
    provider:              'AWS',
    aws_access_key_id:     '...',
    aws_secret_access_key: '...'  
  }
end

I don't want to use lots of Rails.env.development? calls to switch between the configs, and I don't want to store this initializers inside my environment/*.rb files. Is there a way, for example to create a directory for each of my environments under the initializers directory?

initializers
├── development
│   └── carrierwave.rb
├── production
│   └── carrierwave.rb
└── test
    └── carrierwave.rb

The problem according to the Rails guides is following:

You can use subfolders to organize your initializers if you like, because Rails will look into the whole file hierarchy from the initializers folder on down.

Upvotes: 4

Views: 4448

Answers (4)

John Stanfield
John Stanfield

Reputation: 1

I have a Capistrano recipe that does this. Credentials are stored outside the repo (in a folder called /var/secure/) and are symlinked into config/initializers/ on deployment.

namespace :local do
  desc "Symlink all files in /var/secure into config/initializers.  This is how we get production keys into our apps without hard-coding them.  If they're production-only, great.  If there are development and production credentials, put the development credentials in the repo, and they will be overwritten during deploy."
  task :symlink_secure_initializers, :roles => [:app,:api] do
    run "for l in `ls /var/secure/*.rb`; do 
           rm -f #{release_path}/config/initializers/$(basename $l)
           ln -s /var/secure/$(basename $l) #{release_path}/config/initializers/$(basename $l)
         done"
  end
end

after "deploy:update_code", "local:symlink_secure_initializers"

Upvotes: 0

schneikai
schneikai

Reputation: 289

Put your environment specific initializers under /config/environments/initializers/[env] for example /config/environments/initializers/development and add something like this to config/application.rb:

module YourApp
  class Application < Rails::Application
    # Load environment specific initializers from "config/environments/initializers/[current_env]".
    initializer 'load_environment_initializers', after: :load_config_initializers do |app|
      Dir[File.join(File.dirname(__FILE__), 'environments', 'initializers', Rails.env.to_s, '**', '*.rb')].each {|file| require file }
    end

    ...

 end
end

It will require (load) all files from /config/environments/initializers/[env] and its subdirectories just after it has finished loading all regular initializers.

Upvotes: 3

Anirudhan J
Anirudhan J

Reputation: 2072

You can use dotenv gem and use environment variables to change the config across environemnts.

Upvotes: 0

2potatocakes
2potatocakes

Reputation: 2260

You'll have to move into into another directory mate, everything in the initializers folder will get included at boot time.

If you put the above instead into say..

rails_root/config/env_init_files/development

rails_root/config/env_init_files/production

Then you could do something like this..

#at the end of your environment.rb        
Dir["#{Rails.root}/config/env_init_files/#{Rails.env}/**/*"].each { |initializer| require initializer }

Upvotes: 2

Related Questions