Class: Mxrb::Environment

Inherits:
Object
  • Object
show all
Defined in:
lib/mxrb/environment.rb

Overview

Immutable, stdlib-only environment configuration. Loading never mutates process ENV; apply and with are the explicit mutation boundaries.

Defined Under Namespace

Classes: Error, InvalidName, ParseError, Parser

Constant Summary collapse

NAME_PATTERN =
/\A[a-z][a-z0-9_-]*\z/
KEY_PATTERN =
/\A[A-Za-z_][A-Za-z0-9_]*\z/
ALIASES =
{
  'dev' => 'development',
  'development' => 'development',
  'qa' => 'qa',
  'homolog' => 'staging',
  'homologation' => 'staging',
  'staging' => 'staging',
  'prod' => 'production',
  'production' => 'production'
}.freeze
PROFILE_KEYS =
%w[MXRB_ENV RACK_ENV RAILS_ENV].freeze
WITH_MONITOR =
Monitor.new
UNSET =
Object.new.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil, root: Dir.pwd, process: ENV) ⇒ Environment

Returns a new instance of Environment.



45
46
47
48
49
50
51
52
# File 'lib/mxrb/environment.rb', line 45

def initialize(name = nil, root: Dir.pwd, process: ENV)
  @root = File.expand_path(root)
  @process = stringify(process)
  @requested_name = validate_name(name || detected_name)
  @name = ALIASES.fetch(@requested_name, @requested_name)
  @sources = existing_sources.freeze
  @values = load_values.freeze
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



39
40
41
# File 'lib/mxrb/environment.rb', line 39

def name
  @name
end

#requested_nameObject (readonly)

Returns the value of attribute requested_name.



39
40
41
# File 'lib/mxrb/environment.rb', line 39

def requested_name
  @requested_name
end

#rootObject (readonly)

Returns the value of attribute root.



39
40
41
# File 'lib/mxrb/environment.rb', line 39

def root
  @root
end

#sourcesObject (readonly)

Returns the value of attribute sources.



39
40
41
# File 'lib/mxrb/environment.rb', line 39

def sources
  @sources
end

Class Method Details

.load(name = nil, root: Dir.pwd, process: ENV) ⇒ Object



41
42
43
# File 'lib/mxrb/environment.rb', line 41

def self.load(name = nil, root: Dir.pwd, process: ENV)
  new(name, root:, process:)
end

Instance Method Details

#[](key) ⇒ Object



62
# File 'lib/mxrb/environment.rb', line 62

def [](key) = @values[key.to_s]

#apply(target = ENV, overwrite: true) ⇒ Object

Applies to ENV by default only when explicitly called. overwrite: false preserves keys already present in the target.



69
70
71
72
73
74
75
76
# File 'lib/mxrb/environment.rb', line 69

def apply(target = ENV, overwrite: true)
  @values.each do |key, value|
    next if !overwrite && target.key?(key)

    target[key] = value
  end
  target
end

#fetch(key, default = UNSET, &block) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/mxrb/environment.rb', line 54

def fetch(key, default = UNSET, &block)
  normalized = key.to_s
  return @values.fetch(normalized, &block) if block
  return @values.fetch(normalized) if default.equal?(UNSET)

  @values.fetch(normalized, default)
end

#inspectObject



92
93
94
95
# File 'lib/mxrb/environment.rb', line 92

def inspect
  "#<#{self.class} name=#{name.inspect} root=#{root.inspect} " \
    "sources=#{sources.size} keys=#{@values.size}>"
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


63
# File 'lib/mxrb/environment.rb', line 63

def key?(key) = @values.key?(key.to_s)

#to_hObject



65
# File 'lib/mxrb/environment.rb', line 65

def to_h = @values.dup

#with(target = ENV, overwrite: true) ⇒ Object

Applies the configuration for one block and restores the target even if the block raises. Calls are serialized because process ENV is global.



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/mxrb/environment.rb', line 80

def with(target = ENV, overwrite: true)
  WITH_MONITOR.synchronize do
    snapshot = snapshot(target, overwrite:)
    apply(target, overwrite:)
    begin
      yield self
    ensure
      restore(target, snapshot)
    end
  end
end