chamber 0.0.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +718 -127
- data/bin/chamber +277 -0
- data/lib/chamber.rb +63 -65
- data/lib/chamber/file.rb +84 -0
- data/lib/chamber/file_set.rb +265 -0
- data/lib/chamber/namespace_set.rb +141 -0
- data/lib/chamber/rails.rb +3 -0
- data/lib/chamber/rails/railtie.rb +11 -0
- data/lib/chamber/settings.rb +152 -0
- data/lib/chamber/system_environment.rb +145 -0
- data/lib/chamber/version.rb +2 -2
- data/spec/lib/chamber/file_set_spec.rb +212 -0
- data/spec/lib/chamber/file_spec.rb +94 -0
- data/spec/lib/chamber/namespace_set_spec.rb +81 -0
- data/spec/lib/chamber/settings_spec.rb +135 -0
- data/spec/lib/chamber/system_environment_spec.rb +121 -0
- data/spec/lib/chamber_spec.rb +279 -243
- metadata +58 -59
- data/.gitignore +0 -17
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -5
- data/Gemfile +0 -4
- data/Rakefile +0 -6
- data/chamber.gemspec +0 -36
- data/spec/spec_helper.rb +0 -12
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'chamber/namespace_set'
|
2
|
+
require 'chamber/file'
|
3
|
+
require 'chamber/settings'
|
4
|
+
|
5
|
+
###
|
6
|
+
# Internal: Represents a set of settings files that should be considered for
|
7
|
+
# processing. Whether they actually *are* processed depends on their extension
|
8
|
+
# (only *.yml files are processed unless explicitly specified), and whether
|
9
|
+
# their namespace matches one of the namespaces passed to the FileSet (text
|
10
|
+
# after a dash '-' but before the extension is considered the namespace for the
|
11
|
+
# file).
|
12
|
+
#
|
13
|
+
# When converted to settings, files are always processed in the order of least
|
14
|
+
# specific to most specific. So if there are two files:
|
15
|
+
#
|
16
|
+
# * /tmp/settings.yml
|
17
|
+
# * /tmp/settings-blue.yml
|
18
|
+
#
|
19
|
+
# Then '/tmp/settings.yml' will be processed first and '/tmp/settings-blue.yml'
|
20
|
+
# will be processed second (assuming a namespace with the value 'blue' was
|
21
|
+
# passed in).
|
22
|
+
#
|
23
|
+
# If there are multiple namespaces, they will be process in the order that they
|
24
|
+
# appear in the passed in hash. So assuming two files:
|
25
|
+
#
|
26
|
+
# * /tmp/settings-blue.yml
|
27
|
+
# * /tmp/settings-green.yml
|
28
|
+
#
|
29
|
+
# Then:
|
30
|
+
#
|
31
|
+
# ```ruby
|
32
|
+
# FileSet.new files: '/tmp/settings*.yml',
|
33
|
+
# namespaces: ['blue', 'green']
|
34
|
+
# ```
|
35
|
+
#
|
36
|
+
# will process in this order:
|
37
|
+
#
|
38
|
+
# * /tmp/settings-blue.yml
|
39
|
+
# * /tmp/settings-green.yml
|
40
|
+
#
|
41
|
+
# Whereas:
|
42
|
+
#
|
43
|
+
# ```ruby
|
44
|
+
# FileSet.new files: '/tmp/settings*.yml',
|
45
|
+
# namespaces: ['green', 'blue']
|
46
|
+
# ```
|
47
|
+
#
|
48
|
+
# will process in this order:
|
49
|
+
#
|
50
|
+
# * /tmp/settings-green.yml
|
51
|
+
# * /tmp/settings-blue.yml
|
52
|
+
#
|
53
|
+
# Examples:
|
54
|
+
#
|
55
|
+
# ###
|
56
|
+
# # Assuming the following files exist:
|
57
|
+
# #
|
58
|
+
# # /tmp/settings.yml
|
59
|
+
# # /tmp/settings-blue.yml
|
60
|
+
# # /tmp/settings-green.yml
|
61
|
+
# # /tmp/settings/another.yml
|
62
|
+
# # /tmp/settings/another.json
|
63
|
+
# # /tmp/settings/yet_another-blue.yml
|
64
|
+
# # /tmp/settings/yet_another-green.yml
|
65
|
+
# #
|
66
|
+
#
|
67
|
+
# ###
|
68
|
+
# # This will *consider* all files listed but will only process 'settings.yml'
|
69
|
+
# # and 'another.yml'
|
70
|
+
# #
|
71
|
+
# FileSet.new files: ['/tmp/settings.yml',
|
72
|
+
# '/tmp/settings']
|
73
|
+
#
|
74
|
+
# ###
|
75
|
+
# # This will all files in the 'settings' directory but will only process
|
76
|
+
# # 'another.yml' and 'yet_another-blue.yml'
|
77
|
+
# #
|
78
|
+
# FileSet.new(files: '/tmp/settings',
|
79
|
+
# namespaces: {
|
80
|
+
# favorite_color: 'blue' } )
|
81
|
+
#
|
82
|
+
# ###
|
83
|
+
# # Passed in namespaces do not have to be hashes. Hash keys are used only for
|
84
|
+
# # human readability.
|
85
|
+
# #
|
86
|
+
# # This results in the same outcome as the example above.
|
87
|
+
# #
|
88
|
+
# FileSet.new(files: '/tmp/settings',
|
89
|
+
# namespaces: ['blue'])
|
90
|
+
#
|
91
|
+
# ###
|
92
|
+
# # This will process all files listed:
|
93
|
+
# #
|
94
|
+
# FileSet.new(files: [
|
95
|
+
# '/tmp/settings*.yml',
|
96
|
+
# '/tmp/settings',
|
97
|
+
# ],
|
98
|
+
# namespaces: %w{blue green})
|
99
|
+
#
|
100
|
+
# ###
|
101
|
+
# # This is the only way to explicitly specify files which do not end in
|
102
|
+
# # a 'yml' extension.
|
103
|
+
# #
|
104
|
+
# # This is the only example thus far which will process
|
105
|
+
# # '/tmp/settings/another.json'
|
106
|
+
# #
|
107
|
+
# FileSet.new(files: '/tmp/settings/*.json',
|
108
|
+
# namespaces: %w{blue green})
|
109
|
+
#
|
110
|
+
class Chamber
|
111
|
+
class FileSet
|
112
|
+
|
113
|
+
def initialize(options = {})
|
114
|
+
self.namespaces = options.fetch(:namespaces, {})
|
115
|
+
self.paths = options.fetch(:files)
|
116
|
+
end
|
117
|
+
|
118
|
+
###
|
119
|
+
# Internal: Returns an Array of the ordered list of files that was processed
|
120
|
+
# by Chamber in order to get the resulting settings values. This is useful
|
121
|
+
# for debugging if a given settings value isn't quite what you anticipated it
|
122
|
+
# should be.
|
123
|
+
#
|
124
|
+
# Returns an Array of file path strings
|
125
|
+
#
|
126
|
+
def filenames
|
127
|
+
@filenames ||= files.map(&:to_s)
|
128
|
+
end
|
129
|
+
|
130
|
+
###
|
131
|
+
# Internal: Converts the FileSet into a Settings object which represents all
|
132
|
+
# the settings specified in all of the files in the FileSet.
|
133
|
+
#
|
134
|
+
# This can be used in one of two ways. You may either specify a block which
|
135
|
+
# will be passed each file's settings as they are converted, or you can choose
|
136
|
+
# not to pass a block, in which case it will pass back a single completed
|
137
|
+
# Settings object to the caller.
|
138
|
+
#
|
139
|
+
# The reason the block version is used in Chamber.settings is because we want
|
140
|
+
# to be able to load each settings file as it's processed so that we can use
|
141
|
+
# those already-processed settings in subsequently processed settings files.
|
142
|
+
#
|
143
|
+
# Examples:
|
144
|
+
#
|
145
|
+
# ###
|
146
|
+
# # Specifying a Block
|
147
|
+
# #
|
148
|
+
# file_set = FileSet.new files: [ '/path/to/my/settings.yml' ]
|
149
|
+
#
|
150
|
+
# file_set.to_settings do |settings|
|
151
|
+
# # do stuff with each settings
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
#
|
155
|
+
# ###
|
156
|
+
# # No Block Specified
|
157
|
+
# #
|
158
|
+
# file_set = FileSet.new files: [ '/path/to/my/settings.yml' ]
|
159
|
+
# file_set.to_settings
|
160
|
+
#
|
161
|
+
# # => <Chamber::Settings>
|
162
|
+
#
|
163
|
+
def to_settings
|
164
|
+
clean_settings = Settings.new(:namespaces => namespaces)
|
165
|
+
|
166
|
+
files.each_with_object(clean_settings) do |file, settings|
|
167
|
+
if block_given?
|
168
|
+
yield file.to_settings
|
169
|
+
else
|
170
|
+
settings.merge!(file.to_settings)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
protected
|
176
|
+
|
177
|
+
attr_reader :namespaces,
|
178
|
+
:paths
|
179
|
+
|
180
|
+
###
|
181
|
+
# Internal: Allows the paths for the FileSet to be set. It can either be an
|
182
|
+
# object that responds to `#each` like an Array or one that doesn't. In which
|
183
|
+
# case it will be considered a single path.
|
184
|
+
#
|
185
|
+
# All paths will be converted to Pathnames.
|
186
|
+
#
|
187
|
+
def paths=(raw_paths)
|
188
|
+
raw_paths = [raw_paths] unless raw_paths.respond_to? :each
|
189
|
+
|
190
|
+
@paths = raw_paths.map { |path| Pathname.new(path) }
|
191
|
+
end
|
192
|
+
|
193
|
+
###
|
194
|
+
# Internal: Allows the namespaces for the FileSet to be set. An Array or Hash
|
195
|
+
# can be passed; in both cases it will be converted to a NamespaceSet.
|
196
|
+
#
|
197
|
+
def namespaces=(raw_namespaces)
|
198
|
+
@namespaces = NamespaceSet.new(raw_namespaces)
|
199
|
+
end
|
200
|
+
|
201
|
+
###
|
202
|
+
# Internal: The set of files which are considered to be relevant, but with any
|
203
|
+
# duplicates removed.
|
204
|
+
#
|
205
|
+
def files
|
206
|
+
@files ||= -> do
|
207
|
+
sorted_relevant_files = []
|
208
|
+
|
209
|
+
file_globs.each do |glob|
|
210
|
+
current_glob_files = Pathname.glob(glob)
|
211
|
+
relevant_glob_files = relevant_files & current_glob_files
|
212
|
+
|
213
|
+
relevant_glob_files.map! { |file| File.new( path: file,
|
214
|
+
namespaces: namespaces) }
|
215
|
+
|
216
|
+
sorted_relevant_files += relevant_glob_files
|
217
|
+
end
|
218
|
+
|
219
|
+
sorted_relevant_files.uniq
|
220
|
+
end.call
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
def all_files
|
226
|
+
@all_files ||= Pathname.glob(file_globs).sort
|
227
|
+
end
|
228
|
+
|
229
|
+
def non_namespaced_files
|
230
|
+
@non_namespaced_files ||= all_files - namespaced_files
|
231
|
+
end
|
232
|
+
|
233
|
+
def relevant_files
|
234
|
+
@relevant_files ||= non_namespaced_files + relevant_namespaced_files
|
235
|
+
end
|
236
|
+
|
237
|
+
def file_globs
|
238
|
+
@file_globs ||= paths.map do |path|
|
239
|
+
if path.directory?
|
240
|
+
path + '*.yml'
|
241
|
+
else
|
242
|
+
path
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def namespaced_files
|
248
|
+
@namespaced_files ||= all_files.select do |file|
|
249
|
+
file.fnmatch? '*-*'
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def relevant_namespaced_files
|
254
|
+
file_holder = []
|
255
|
+
|
256
|
+
namespaces.each do |namespace|
|
257
|
+
file_holder << namespaced_files.select do |file|
|
258
|
+
file.fnmatch? "*-#{namespace}.???"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
file_holder.flatten
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
###
|
4
|
+
# Internal: Respresents a set of namespaces which will be processed by Chamber
|
5
|
+
# at various stages when settings are loaded.
|
6
|
+
#
|
7
|
+
# The main function that this class provides is the ability to create
|
8
|
+
# a NamespaceSet from either an array-like or hash-like object and the ability
|
9
|
+
# to allow callables to be passed which will then be executed.
|
10
|
+
#
|
11
|
+
class Chamber
|
12
|
+
class NamespaceSet
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
###
|
16
|
+
# Internal: Creates a new NamespaceSet from arrays, hashes and sets.
|
17
|
+
#
|
18
|
+
def initialize(raw_namespaces = {})
|
19
|
+
self.namespaces = raw_namespaces
|
20
|
+
end
|
21
|
+
|
22
|
+
###
|
23
|
+
# Internal: Allows a NamespaceSet to be combined with some other array-like
|
24
|
+
# object.
|
25
|
+
#
|
26
|
+
# It does not mutate the source NamespaceSet but rather creates a new one and
|
27
|
+
# returns it.
|
28
|
+
#
|
29
|
+
# Examples:
|
30
|
+
#
|
31
|
+
# # Can be an Array
|
32
|
+
# namespace_set = NamespaceSet.new ['value_1', 'value_2']
|
33
|
+
# namespace_set + ['value_3']
|
34
|
+
# # => <NamespaceSet namespaces=['value_1', 'value_2', 'value_3']>
|
35
|
+
#
|
36
|
+
# # Can be a Set
|
37
|
+
# namespace_set = NamespaceSet.new ['value_1', 'value_2']
|
38
|
+
# namespace_set + Set['value_3']
|
39
|
+
# # => <NamespaceSet namespaces=['value_1', 'value_2', 'value_3']>
|
40
|
+
#
|
41
|
+
# # Can be a object which is convertable to an Array
|
42
|
+
# namespace_set = NamespaceSet.new ['value_1', 'value_2']
|
43
|
+
# namespace_set + (1..3)
|
44
|
+
# # => <NamespaceSet namespaces=['value_1', 'value_2', '1', '2', '3']>
|
45
|
+
#
|
46
|
+
# Returns a NamespaceSet
|
47
|
+
#
|
48
|
+
def +(other)
|
49
|
+
NamespaceSet.new namespaces + other.to_a
|
50
|
+
end
|
51
|
+
|
52
|
+
###
|
53
|
+
# Internal: Iterates over each namespace value and allows it to be used in
|
54
|
+
# a block.
|
55
|
+
#
|
56
|
+
def each
|
57
|
+
namespaces.each do |namespace|
|
58
|
+
yield namespace
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
###
|
63
|
+
# Internal: Converts a NamespaceSet into an Array consisting of the namespace
|
64
|
+
# values stored in the set.
|
65
|
+
#
|
66
|
+
# Returns an Array
|
67
|
+
#
|
68
|
+
def to_ary
|
69
|
+
namespaces.to_a
|
70
|
+
end
|
71
|
+
|
72
|
+
alias_method :to_a, :to_ary
|
73
|
+
|
74
|
+
###
|
75
|
+
# Internal: Determines whether a NamespaceSet is equal to another array-like
|
76
|
+
# object.
|
77
|
+
#
|
78
|
+
# Returns a Boolean
|
79
|
+
#
|
80
|
+
def ==(other)
|
81
|
+
self.to_ary.eql? other.to_ary
|
82
|
+
end
|
83
|
+
|
84
|
+
###
|
85
|
+
# Internal: Determines whether a NamespaceSet is equal to another
|
86
|
+
# NamespaceSet.
|
87
|
+
#
|
88
|
+
# Returns a Boolean
|
89
|
+
#
|
90
|
+
def eql?(other)
|
91
|
+
other.is_a?( Chamber::NamespaceSet) &&
|
92
|
+
self.namespaces == other.namespaces
|
93
|
+
end
|
94
|
+
|
95
|
+
protected
|
96
|
+
|
97
|
+
def namespaces
|
98
|
+
@namespaces ||= Set.new
|
99
|
+
end
|
100
|
+
|
101
|
+
###
|
102
|
+
# Internal: Sets the namespaces for the set from a variety of objects and
|
103
|
+
# processes them by checking to see if they can be 'called'.
|
104
|
+
#
|
105
|
+
# Examples:
|
106
|
+
#
|
107
|
+
# namespace_set = NamespaceSet.new
|
108
|
+
#
|
109
|
+
# # Can be set to an array
|
110
|
+
# namespace_set.namespaces = %w{namespace_value_1 namespace_value_2}
|
111
|
+
# # => ['namespace_value_1', 'namespace_value_2']
|
112
|
+
#
|
113
|
+
# # Can be set to a hash
|
114
|
+
# namespace_set.namespaces = { environment: 'development',
|
115
|
+
# hostname: 'my host' }
|
116
|
+
# namespace_set.namespaces
|
117
|
+
# # => ['development', 'my host']
|
118
|
+
#
|
119
|
+
# # Can be set to a callable
|
120
|
+
# namespace_set.namespaces = { environment: -> { 'called' } }
|
121
|
+
# namespace_set.namespaces
|
122
|
+
# # => ['called']
|
123
|
+
#
|
124
|
+
# # Does not allow duplicate items
|
125
|
+
# namespace_set.namespaces = %w{namespace_value namespace_value}
|
126
|
+
# namespace_set.namespaces
|
127
|
+
# # => ['namespace_value']
|
128
|
+
#
|
129
|
+
def namespaces=(raw_namespaces)
|
130
|
+
namespace_values = if raw_namespaces.respond_to? :values
|
131
|
+
raw_namespaces.values
|
132
|
+
else
|
133
|
+
raw_namespaces
|
134
|
+
end
|
135
|
+
|
136
|
+
@namespaces = Set.new namespace_values.map do |value|
|
137
|
+
value.respond_to?(:call) ? value.call : value
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Chamber
|
2
|
+
module Rails
|
3
|
+
class Railtie < ::Rails::Railtie
|
4
|
+
initializer 'chamber.load', before: :load_environment_config do
|
5
|
+
Chamber.load( :basepath => ::Rails.root.join('config'),
|
6
|
+
:namespaces => {
|
7
|
+
:environment => -> { ::Rails.env } })
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'hashie/mash'
|
2
|
+
require 'chamber/system_environment'
|
3
|
+
require 'chamber/namespace_set'
|
4
|
+
|
5
|
+
###
|
6
|
+
# Internal: Represents the base settings storage needed for Chamber.
|
7
|
+
#
|
8
|
+
class Chamber
|
9
|
+
class Settings
|
10
|
+
|
11
|
+
attr_reader :namespaces
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
self.namespaces = options.fetch(:namespaces, NamespaceSet.new)
|
15
|
+
self.data = options.fetch(:settings, Hashie::Mash.new)
|
16
|
+
end
|
17
|
+
|
18
|
+
###
|
19
|
+
# Internal: Converts a Settings object into a hash that is compatible as an
|
20
|
+
# environment variable hash.
|
21
|
+
#
|
22
|
+
# Example:
|
23
|
+
#
|
24
|
+
# settings = Settings.new settings: {
|
25
|
+
# my_setting: 'my value',
|
26
|
+
# my_sub_setting: {
|
27
|
+
# my_sub_sub_setting_1: 'my sub value 1',
|
28
|
+
# my_sub_sub_setting_2: 'my sub value 2',
|
29
|
+
# }
|
30
|
+
# settings.to_environment
|
31
|
+
# # => {
|
32
|
+
# 'MY_SETTING' => 'my value',
|
33
|
+
# 'MY_SUB_SETTING_MY_SUB_SUB_SETTING_1' => 'my sub value 1',
|
34
|
+
# 'MY_SUB_SETTING_MY_SUB_SUB_SETTING_2' => 'my sub value 2',
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
# Returns a Hash sorted alphabetically by the names of the keys
|
38
|
+
#
|
39
|
+
def to_environment
|
40
|
+
Hash[SystemEnvironment.extract_from(data).sort]
|
41
|
+
end
|
42
|
+
|
43
|
+
###
|
44
|
+
# Internal: Converts a Settings object into a String with a format that will
|
45
|
+
# work well when working with the shell.
|
46
|
+
#
|
47
|
+
# Examples:
|
48
|
+
#
|
49
|
+
# Settings.new( settings: {
|
50
|
+
# my_key: 'my value',
|
51
|
+
# my_other_key: 'my other value',
|
52
|
+
# } ).to_s
|
53
|
+
# # => 'MY_KEY="my value" MY_OTHER_KEY="my other value"'
|
54
|
+
#
|
55
|
+
def to_s(options = {})
|
56
|
+
pair_separator = options[:pair_separator] || ' '
|
57
|
+
value_surrounder = options[:value_surrounder] || '"'
|
58
|
+
name_value_separator = options[:name_value_separator] || '='
|
59
|
+
|
60
|
+
pairs = to_environment.to_a.map do |pair|
|
61
|
+
%Q{#{pair[0]}#{name_value_separator}#{value_surrounder}#{pair[1]}#{value_surrounder}}
|
62
|
+
end
|
63
|
+
|
64
|
+
pairs.join(pair_separator)
|
65
|
+
end
|
66
|
+
|
67
|
+
###
|
68
|
+
# Internal: Merges a Settings object with another Settings object or
|
69
|
+
# a hash-like object.
|
70
|
+
#
|
71
|
+
# Also, if merging Settings, it will merge the namespaces as well.
|
72
|
+
#
|
73
|
+
# Example:
|
74
|
+
#
|
75
|
+
# settings = Settings.new settings: { my_setting: 'my value' }
|
76
|
+
# other_settings = Settings.new settings: { my_other_setting: 'my other value' }
|
77
|
+
#
|
78
|
+
# settings.merge! other_settings
|
79
|
+
#
|
80
|
+
# settings
|
81
|
+
# # => {
|
82
|
+
# 'my_setting' => 'my value',
|
83
|
+
# 'my_other_setting' => 'my other value',
|
84
|
+
# }
|
85
|
+
#
|
86
|
+
# Returns a Hash
|
87
|
+
#
|
88
|
+
def merge!(other)
|
89
|
+
self.data = data.merge(other.to_hash)
|
90
|
+
self.namespaces = (namespaces + other.namespaces) if other.respond_to? :namespaces
|
91
|
+
end
|
92
|
+
|
93
|
+
def eql?(other)
|
94
|
+
other.is_a?( Chamber::Settings) &&
|
95
|
+
self.data == other.data &&
|
96
|
+
self.namespaces == other.namespaces
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_hash
|
100
|
+
data
|
101
|
+
end
|
102
|
+
|
103
|
+
def method_missing(name, *args)
|
104
|
+
return data.public_send(name, *args) if data.respond_to?(name)
|
105
|
+
|
106
|
+
super
|
107
|
+
end
|
108
|
+
|
109
|
+
def respond_to_missing?(name, include_private = false)
|
110
|
+
data.respond_to?(name, include_private)
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
attr_reader :raw_data
|
116
|
+
attr_writer :namespaces
|
117
|
+
|
118
|
+
def data
|
119
|
+
@data ||= Hashie::Mash.new
|
120
|
+
end
|
121
|
+
|
122
|
+
def data=(raw_data)
|
123
|
+
@raw_data = Hashie::Mash.new(raw_data)
|
124
|
+
|
125
|
+
namespace_checked_data = if data_is_namespaced?
|
126
|
+
namespace_filtered_data
|
127
|
+
else
|
128
|
+
self.raw_data
|
129
|
+
end
|
130
|
+
|
131
|
+
@data = SystemEnvironment.inject_into(namespace_checked_data)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def data_is_namespaced?
|
137
|
+
@data_is_namespaced ||= raw_data.keys.any? { |key| namespaces.include? key }
|
138
|
+
end
|
139
|
+
|
140
|
+
def namespace_filtered_data
|
141
|
+
@namespace_filtered_data ||= -> do
|
142
|
+
data = Hashie::Mash.new
|
143
|
+
|
144
|
+
namespaces.each do |namespace|
|
145
|
+
data.merge!(raw_data[namespace]) if raw_data[namespace]
|
146
|
+
end
|
147
|
+
|
148
|
+
data
|
149
|
+
end.call
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|