Module: Dotenv

Extended by:
Dotenv
Included in:
Dotenv
Defined in:
lib/dotenv.rb,
lib/dotenv/cli.rb,
lib/dotenv/diff.rb,
lib/dotenv/rails.rb,
lib/dotenv/parser.rb,
lib/dotenv/version.rb,
lib/dotenv/template.rb,
lib/dotenv/environment.rb,
lib/dotenv/missing_keys.rb,
lib/dotenv/replay_logger.rb,
lib/dotenv/log_subscriber.rb,
lib/dotenv/substitutions/command.rb,
lib/dotenv/substitutions/variable.rb

Overview

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

Defined Under Namespace

Modules: Substitutions Classes: CLI, Diff, EnvTemplate, Environment, Error, FormatError, LogSubscriber, MissingKeys, Parser, Rails, ReplayLogger

Constant Summary collapse

Railtie =
ActiveSupport::Deprecation::DeprecatedConstantProxy.new("Dotenv::Railtie", "Dotenv::Rails", Dotenv::Rails.deprecator)
VERSION =
"3.1.8".freeze
EXPORT_COMMAND =
"export ".freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#instrumenterObject

Returns the value of attribute instrumenter.



15
16
17
# File 'lib/dotenv.rb', line 15

def instrumenter
  @instrumenter
end

Instance Method Details

#load(*filenames, overwrite: false, ignore: true) ⇒ Object

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



18
19
20
21
22
23
24
# 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) ⇒ Object

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



27
28
29
# File 'lib/dotenv.rb', line 27

def load!(*filenames)
  load(*filenames, ignore: false)
end

#modify(env = {}, &block) ⇒ Object

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.

Parameters:

  • env (Hash) (defaults to: {})

    Hash of keys and values to set in ENV



116
117
118
119
120
121
122
123
124
# 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

#overwrite(*filenames) ⇒ Object Also known as: overload

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



32
33
34
# File 'lib/dotenv.rb', line 32

def overwrite(*filenames)
  load(*filenames, overwrite: true)
end

#overwrite!(*filenames) ⇒ Object Also known as: overload!

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



38
39
40
# File 'lib/dotenv.rb', line 38

def overwrite!(*filenames)
  load(*filenames, overwrite: true, ignore: false)
end

#parse(*filenames, overwrite: false, ignore: true, &block) ⇒ Hash

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

Parameters:

  • filenames (String, Array<String>)

    Files to parse

  • overwrite (Boolean) (defaults to: false)

    Overwrite existing ENV values

  • ignore (Boolean) (defaults to: true)

    Ignore non-existent files

  • block (Proc)

    Block to yield for each parsed Dotenv::Environment

Returns:

  • (Hash)

    parsed key/value pairs



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 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, Errno::EISDIR
      raise unless ignore
    end

    hash.merge! env || {}
  end
end

#require_keys(*keys) ⇒ Object

Raises:



126
127
128
129
130
# 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) ⇒ Object

Restore ENV to a given state

Parameters:

  • env (Hash) (defaults to: @diff&.a)

    Hash of keys and values to restore, defaults to the last saved state

  • safe (Boolean) (defaults to: Thread.current == Thread.main)

    Is it safe to modify ENV? Defaults to true in the main thread, otherwise raises an error.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# 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

#saveObject

Save the current ENV to be restored later



67
68
69
70
71
# File 'lib/dotenv.rb', line 67

def save
  instrument(:save) do |payload|
    @diff = payload[:diff] = Dotenv::Diff.new
  end
end

#update(env = {}, overwrite: false) ⇒ Object

Update ENV with the given hash of keys and values

Parameters:

  • env (Hash) (defaults to: {})

    Hash of keys and values to set in ENV

  • overwrite (Boolean) (defaults to: false)

    Overwrite existing ENV values



98
99
100
101
102
103
104
105
106
107
108
# 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