In regards to my comment on bkeepers/dotenv#120
ENV
config/**/env
.env
config/**/env.#{Rails.env}
.env.#{Rails.env}
config/env.local
.env.local
config/env.#{Rails.env}.local
.env.#{Rails.env}.local
- original
ENV
- merged last unless calling Dotenv.overload
Result: Environments are merged in that order (last wins), but don't override existing ENV variables (which presumably come from the external environment)
Result: Environments are merged in that order (last wins), and any conflicting ENV variables are overridden.
- The environment is the source of truth; dotenv is just there so you don't have to export a bunch of environment variables.
- The base
.env
file contains most of your config. Additional Rails-environment-specific files tweak them per-environment (development, test, production). Your.env.local
is meant to be gitignored and let you deviate from the shared config just for your machine. - One-off environment variables can be used to override the defaults set in your dotenv files (e.g.
SOME_VAR=1 rails runner "puts ENV['SOME_VAR']"
=> 1). - If you do check in your .env files and then deploy to Heroku, it will
still work because it preserves the environment set by Heroku. Your Heroku app vars will win and
.env
will just fill in any missing vars. This is an optimistic approach to managing your app configuration: the app doesn't blow up when you deploy but have forgotten to set a variable on Heroku. - Dotfiles are meant to be hidden, so they don't clutter up your view when you're looking at real files/folders. The config directory is a place to get config files out of the root of the app. Both serve similar purposes and this scheme lets you choose where you think developers will find your configs more easily: hidden in the root or visible in
config/
. Prefixing env files inconfig/
with a dot is obtuse. - The
.local
suffix is consistent with this dotfile convention
- Assume load will only be called once.
.load
merges all the .env files before applying the result to the environment. - Save a copy of ENV to a module var before Dotenv ever touches ENV.
Every time
.load
is called, re-merge that original environment last. This will give the most flexibility if someone wants to redefine the set of files provided toDotenv.load
in a Rails initializer, for example.