Better way to organize Rails initializers
in my current Rails project I ended 开发者_如何学Goup 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.
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.
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 }
You can use dotenv gem and use environment variables to change the config across environemnts.
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"
精彩评论