Skip to content

class Athena::Dotenv
inherits Reference #

All usage involves using an Athena::Dotenv instance. For example:

require "athena-dotenv"

# Create a new instance
dotenv = Athena::Dotenv.new

# Load a file
dotenv.load "./.env"

# Load multiple files
dotenv.load "./.env", "./.env.dev"

# Overrides existing variables
dotenv.overload "./.env"

# Load all files for the current $APP_ENV
# .env, .env.local, and .env.$APP_ENV.local or .env.$APP_ENV
dotenv.load_environment "./.env"
A Athena::Dotenv::Exception::Path error will be raised if the provided file was not found, or is not readable.

Syntax#

ENV vars should be defined one per line. There should be no space between the = between the var name and its value.

DATABASE_URL=mysql://db_user:[email protected]:3306/db_name

AAthena::Dotenv::Exception::Format error will be raised if a formatting/parsing error is encountered.

Comments#

Comments can be defined by prefixing them with a # character. Comments can defined on its own line, or inlined after an ENV var definition.

# Single line comment
FOO=BAR

BAR=BAZ # Inline comment

Quotes#

Unquoted values, or those quoted with single (') quotes behave as literals while double (") quotes will have special chars expanded. For example, given the following .env file:

UNQUOTED=FOO\nBAR
SINGLE_QUOTES='FOO\nBAR'
DOUBLE_QUOTES="FOO\nBAR"
require "athena-dotenv"

Athena::Dotenv.new.load "./.env"

ENV["UNQUOTED"]      # => "FOO\\nBAR"
ENV["SINGLE_QUOTES"] # => "FOO\\nBAR"
ENV["DOUBLE_QUOTES"] # => "FOO\n" + "BAR"

Notice how only the double quotes version actually expands \n into a newline, whereas the others treat it as a literal \n.

Quoted values may also extend over multiple lines:

FOO="FOO
BAR\n
BAZ"

Both single and double quotes will include the actual newline characters, however only double quotes would expand the extra newline in BAR\n.

Variables#

ENV vars can be used in values by prefixing the variable name with a $ with optional opening and closing {}.

FOO=BAR
BAZ=$FOO
BIZ=${BAZ}

Warning

The order is important when using variables. In the previous example FOO must be defined BAZ which must be defined before BIZ. This also extends to when loading multiple files, where a variable may use the value in another file.

Default values may also be defined in case the related ENV var is not set:

DB_USER=${DB_USER:-root}

This would set the value of DB_USER to be root, unless DB_USER is defined elsewhere in which case it would use the value of that variable.

Commands#

Shell commands can be evaluated via $().

Note

Commands are currently not supported on Windows.

DATE=$(date)

File Precedence#

The default .env file defines ALL ENV vars used within an application, with sane defaults. This file should be committed and should not contain any sensitive values.

However in some cases you may need to define values to override those in .env, whether that be only for a single machine, or all machines in a specific environment.

For these purposes there are other .env files that are loaded in a specific order to allow for just this use case:

  • .env - Defines all ENV vars, and their default values, used by the application.
  • .env.local - Overrides ENV vars for all environments, but only for the machine that contains the file. This file should NOT be committed, and is ignored in the test environment to ensure reproducibility.
  • .env.<environment> (e.g. .env.test) - Overrides ENV vars for only this one environment. These files SHOULD be committed.
  • .env.<environment>.local (e.g. .env.test.local) - Machine-specific overrides, but only for a single environment. This file should NOT be committed.

See #load_environment for more information.

Note

Real ENV vars always win against those created in any .env file.

Tip

Environment specific .env files should ONLY to override values defined within the default .env file and NOT as a replacement to it. This ensures there is still a single source of truth and removes the need to duplicate everything for each environment.

Production#

.env files are mainly intended for non-production environments in order to give the benefits of using ENV vars, but be more convenient/easier to use. They can of course continue to be used in production by distributing the base .env file along with the binary, then creating a .env.local on the production server and including production values within it. This can work quite well for simple applications, but ultimately a more robust solution that best leverages the features of the server the application is running on is best.

Constants#

VERSION = "0.1.3"#

Constructors#

.load(path : String | Path = ".env", *paths : String | Path) : self#

Convenience method that loads one or more .env files, defaulting to .env.

View source

.new(env_key : String = "APP_ENV")#

View source

Methods#

#load(*paths : String | Path) : Nil#

Loads each .env file within the provided paths.

require "athena-dotenv"

dotenv = Athena::Dotenv.new

dotenv.load "./.env"
dotenv.load "./.env", "./.env.dev"
View source

#load_environment(path : String | Path, env_key : String | Nil = nil, default_environment : String = "dev", test_environments : Enumerable(String) = {"test"}, override_existing_vars : Bool = false) : Nil#

Loads a .env file and its related additional files based on their precedence if they exist.

The current ENV is determined by the value of APP_ENV, which is configurable globally via .new, or for a single load via the env_key parameter. If no environment ENV var is defined, default_environment will be used. The .env.local file will NOT be loaded if the current environment is included within test_environments.

Existing ENV vars may optionally be overridden by passing true to override_existing_vars.

require "athena-dotenv"

dotenv = Athena::Dotenv.new

# Use `APP_ENV`, or `dev`
dotenv.load_environment "./.env"

# Custom *env_key* and *default_environment*
dotenv.load_environment "./.env", "ATHENA_ENV", "qa"
View source

#overload(*paths : String | Path) : Nil#

Same as #load, but will override existing ENV vars.

View source

#parse(data : String, path : String | Path = ".env") : Hash(String, String)#

Parses and returns a Hash based on the string contents of the provided data string. The original .env file path may also be provided to path for more meaningful error messages.

require "athena-dotenv"

path = "/path/to/.env"
dotenv = Athena::Dotenv.new

File.write path, "FOO=BAR"

dotenv.parse File.read(path), path # => {"FOO" => "BAR"}
View source

#populate(values : Hash(String, String), override_existing_vars : Bool = false) : Nil#

Populates the provides values into the environment.

Existing ENV vars may optionally be overridden by passing true to override_existing_vars.

require "athena-dotenv"

ENV["FOO"]? # => nil

Athena::Dotenv.new.populate({"FOO" => "BAR"})

ENV["FOO"]? # => "BAR"
View source