module Dotenv

Shim to load environment variables from ‘.env files into `ENV`.

Constants

EXPORT_COMMAND
Railtie
SEMAPHORE

An internal monitor to synchronize access to ENV in multi-threaded environments.

VERSION

Attributes

instrumenter[RW]

Public Instance Methods

load(*filenames, overwrite: false, ignore: true) click to toggle source

Loads environment variables from one or more ‘.env` files. See `#parse` for more details.

# File lib/dotenv.rb, line 18
def load(*filenames, overwrite: false, ignore: true)
  parse(*filenames, overwrite: overwrite, ignore: ignore) do |env|
    instrument(:load, env: env) do |payload|
      update(env, overwrite: overwrite)
    end
  end
end
load!(*filenames) click to toggle source

Same as ‘#load`, but raises Errno::ENOENT if any files don’t exist

# File lib/dotenv.rb, line 27
def load!(*filenames)
  load(*filenames, ignore: false)
end
modify(env = {}, &block) click to toggle source

Modify ‘ENV` for the block and restore it to its previous state afterwards.

Note that the block is synchronized to prevent concurrent modifications to ‘ENV`, so multiple threads will be executed serially.

@param env [Hash] Hash of keys and values to set in ‘ENV`

# File lib/dotenv.rb, line 116
def modify(env = {}, &block)
  SEMAPHORE.synchronize do
    diff = Dotenv::Diff.new
    update(env, overwrite: true)
    block.call
  ensure
    restore(diff.a, safe: true)
  end
end
overload(*filenames)
Alias for: overwrite
overload!(*filenames)
Alias for: overwrite!
overwrite(*filenames) click to toggle source

same as ‘#load`, but will overwrite existing values in `ENV`

# File lib/dotenv.rb, line 32
def overwrite(*filenames)
  load(*filenames, overwrite: true)
end
Also aliased as: overload
overwrite!(*filenames) click to toggle source

same as ‘#overwrite`, but raises Errno::ENOENT if any files don’t exist

# File lib/dotenv.rb, line 38
def overwrite!(*filenames)
  load(*filenames, overwrite: true, ignore: false)
end
Also aliased as: overload!
parse(*filenames, overwrite: false, ignore: true, &block) click to toggle source

Parses the given files, yielding for each file if a block is given.

@param filenames [String, Array<String>] Files to parse @param overwrite [Boolean] Overwrite existing ‘ENV` values @param ignore [Boolean] Ignore non-existent files @param block [Proc] Block to yield for each parsed `Dotenv::Environment` @return [Hash] parsed key/value pairs

# File lib/dotenv.rb, line 50
def parse(*filenames, overwrite: false, ignore: true, &block)
  filenames << ".env" if filenames.empty?
  filenames = filenames.reverse if overwrite

  filenames.reduce({}) do |hash, filename|
    begin
      env = Environment.new(File.expand_path(filename), overwrite: overwrite)
      env = block.call(env) if block
    rescue Errno::ENOENT
      raise unless ignore
    end

    hash.merge! env || {}
  end
end
require_keys(*keys) click to toggle source
# File lib/dotenv.rb, line 126
def require_keys(*keys)
  missing_keys = keys.flatten - ::ENV.keys
  return if missing_keys.empty?
  raise MissingKeys, missing_keys
end
restore(env = @diff&.a, safe: Thread.current == Thread.main) click to toggle source

Restore ‘ENV` to a given state

@param env [Hash] Hash of keys and values to restore, defaults to the last saved state @param safe [Boolean] Is it safe to modify ‘ENV`? Defaults to `true` in the main thread, otherwise raises an error.

# File lib/dotenv.rb, line 77
  def restore(env = @diff&.a, safe: Thread.current == Thread.main)
    # No previously saved or provided state to restore
    return unless env

    diff = Dotenv::Diff.new(b: env)
    return unless diff.any?

    unless safe
      raise ThreadError, <<~EOE.tr("\n", " ")
        Dotenv.restore is not thread safe. Use `Dotenv.modify { }` to update ENV for the duration
        of the block in a thread safe manner, or call `Dotenv.restore(safe: true)` to ignore
        this error.
      EOE
    end
    instrument(:restore, diff: diff) { ENV.replace(env) }
  end
save() click to toggle source

Save the current ‘ENV` to be restored later

# File lib/dotenv.rb, line 67
def save
  instrument(:save) do |payload|
    @diff = payload[:diff] = Dotenv::Diff.new
  end
end
update(env = {}, overwrite: false) click to toggle source

Update ‘ENV` with the given hash of keys and values

@param env [Hash] Hash of keys and values to set in ‘ENV` @param overwrite [Boolean] Overwrite existing `ENV` values

# File lib/dotenv.rb, line 98
def update(env = {}, overwrite: false)
  instrument(:update) do |payload|
    diff = payload[:diff] = Dotenv::Diff.new do
      ENV.update(env.transform_keys(&:to_s)) do |key, old_value, new_value|
        # This block is called when a key exists. Return the new value if overwrite is true.
        overwrite ? new_value : old_value
      end
    end
    diff.env
  end
end

Private Instance Methods

instrument(name, payload = {}, &block) click to toggle source
# File lib/dotenv.rb, line 134
def instrument(name, payload = {}, &block)
  if instrumenter
    instrumenter.instrument("#{name}.dotenv", payload, &block)
  else
    block&.call payload
  end
end