class Athena::Dotenv

Overview

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::Exceptions::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::Exceptions::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:

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.

Defined in:

athena-dotenv.cr:1
athena-dotenv.cr:144

Constant Summary

VERSION = "0.1.3"

Constructors

Instance Method Summary

Constructor Detail

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

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


[View source]
def self.new(env_key : String = "APP_ENV") #

[View source]

Instance Method Detail

def 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]
def 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][Athena::Dotenv--file-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]
def overload(*paths : String | Path) : Nil #

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


[View source]
def 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]
def 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]