configurator.rb
1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
require 'ostruct'
# Configurator maps lists of environment variables to names that you define in
# order to provide a consistent way to use configuration throughout your
# application
class Configurator
# Run the configurator and return the processed values
#
# @example Simple mapping
# ENV['BAR'] = 'onevalue'
# ENV['BAZ'] = 'another'
#
# config = Configurator.run({
# key_one: ['FOO', 'BAR'],
# key_two: ['BAZ']
# })
#
# config.key_one
# #=> 'onevalue'
# config.key_two
# #=> 'another'
#
# @example Using override blocks
# ENV['BAR'] = 'onevalue'
# ENV['BAZ'] = 'another'
#
# config = Configurator.run({
# key_one: ['FOO', 'BAR', ->(values) {
# values[:key_two]
# }],
# key_two: ['BAZ']
# })
#
# config.key_one
# #=> 'another'
#
# @param Hash map of configuration keys with array values where the array is
# a list of environment variables to scan for configuration
# @return OpenStruct configuration object
def self.run(mapping)
reader = new(mapping)
reader.read
end
# Create the Configurator object
#
# @param [Hash] mapping mapping of config names to environment value names
# @return [Configurator]
def initialize(mapping)
@mapping = mapping
@overrides = {}
@storage = {}
end
# Process the environment variable values and store the overrides
def scan
@mapping.each do |key, values|
@overrides[key] = values.pop if values.last.is_a? Proc
env_name = values.find { |v| ENV[v] }
@storage[key] = YAML.parse(ENV[env_name]).to_ruby if env_name
end
end
# Apply the override functions
def apply_overrides
@overrides.each do |key, override|
@storage[key] = override.call(@storage)
end
end
# Perform all the required processing and return the configuration object
#
# @return [OpenStruct] configuration object
def read
@storage = {}
scan
apply_overrides
OpenStruct.new(@storage)
end
end