env_parser 0.8.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +7 -6
- data/.rubocop.yml +56 -57
- data/.ruby-version +1 -1
- data/Gemfile.lock +58 -28
- data/README.md +252 -176
- data/docs/EnvParser.html +305 -169
- data/docs/EnvParser/AutoregisterFileNotFound.html +143 -0
- data/docs/EnvParser/Error.html +9 -9
- data/docs/EnvParser/TypeAlreadyDefinedError.html +143 -0
- data/docs/EnvParser/Types.html +128 -0
- data/docs/EnvParser/Types/BaseTypes.html +177 -0
- data/docs/EnvParser/Types/ChronologyTypes.html +159 -0
- data/docs/EnvParser/Types/InternetTypes.html +159 -0
- data/docs/EnvParser/UnknownTypeError.html +143 -0
- data/docs/EnvParser/UnparseableAutoregisterSpec.html +143 -0
- data/docs/EnvParser/ValueNotAllowedError.html +143 -0
- data/docs/EnvParser/ValueNotConvertibleError.html +143 -0
- data/docs/EnvParserTypes.html +129 -0
- data/docs/EnvParserTypes/BaseTypes.html +178 -0
- data/docs/EnvParserTypes/ChronologyTypes.html +159 -0
- data/docs/EnvParserTypes/InternetTypes.html +159 -0
- data/docs/EnvParserTypes/TimeTypes.html +158 -0
- data/docs/_index.html +108 -9
- data/docs/class_list.html +3 -3
- data/docs/css/style.css +7 -9
- data/docs/file.README.html +215 -226
- data/docs/file_list.html +2 -2
- data/docs/frames.html +2 -2
- data/docs/index.html +215 -226
- data/docs/js/app.js +69 -3
- data/docs/method_list.html +13 -5
- data/docs/top-level-namespace.html +9 -9
- data/env_parser.gemspec +6 -2
- data/lib/env_parser.rb +111 -83
- data/lib/env_parser/autoregister.rb +3 -0
- data/lib/env_parser/errors.rb +40 -0
- data/lib/env_parser/types.rb +3 -0
- data/lib/env_parser/types/base_types.rb +99 -26
- data/lib/env_parser/types/chronology_types.rb +104 -0
- data/lib/env_parser/types/internet_types.rb +99 -0
- data/lib/env_parser/version.rb +1 -1
- metadata +85 -10
data/docs/js/app.js
CHANGED
@@ -120,6 +120,49 @@ function summaryToggle() {
|
|
120
120
|
} else { localStorage.summaryCollapsed = "expand"; }
|
121
121
|
}
|
122
122
|
|
123
|
+
function constantSummaryToggle() {
|
124
|
+
$('.constants_summary_toggle').click(function(e) {
|
125
|
+
e.preventDefault();
|
126
|
+
localStorage.summaryCollapsed = $(this).text();
|
127
|
+
$('.constants_summary_toggle').each(function() {
|
128
|
+
$(this).text($(this).text() == "collapse" ? "expand" : "collapse");
|
129
|
+
var next = $(this).parent().parent().nextAll('dl.constants').first();
|
130
|
+
if (next.hasClass('compact')) {
|
131
|
+
next.toggle();
|
132
|
+
next.nextAll('dl.constants').first().toggle();
|
133
|
+
}
|
134
|
+
else if (next.hasClass('constants')) {
|
135
|
+
var list = $('<dl class="constants compact" />');
|
136
|
+
list.html(next.html());
|
137
|
+
list.find('dt').each(function() {
|
138
|
+
$(this).addClass('summary_signature');
|
139
|
+
$(this).text( $(this).text().split('=')[0]);
|
140
|
+
if ($(this).has(".deprecated").length) {
|
141
|
+
$(this).addClass('deprecated');
|
142
|
+
};
|
143
|
+
});
|
144
|
+
// Add the value of the constant as "Tooltip" to the summary object
|
145
|
+
list.find('pre.code').each(function() {
|
146
|
+
console.log($(this).parent());
|
147
|
+
var dt_element = $(this).parent().prev();
|
148
|
+
var tooltip = $(this).text();
|
149
|
+
if (dt_element.hasClass("deprecated")) {
|
150
|
+
tooltip = 'Deprecated. ' + tooltip;
|
151
|
+
};
|
152
|
+
dt_element.attr('title', tooltip);
|
153
|
+
});
|
154
|
+
list.find('.docstring, .tags, dd').remove();
|
155
|
+
next.before(list);
|
156
|
+
next.toggle();
|
157
|
+
}
|
158
|
+
});
|
159
|
+
return false;
|
160
|
+
});
|
161
|
+
if (localStorage.summaryCollapsed == "collapse") {
|
162
|
+
$('.constants_summary_toggle').first().click();
|
163
|
+
} else { localStorage.summaryCollapsed = "expand"; }
|
164
|
+
}
|
165
|
+
|
123
166
|
function generateTOC() {
|
124
167
|
if ($('#filecontents').length === 0) return;
|
125
168
|
var _toc = $('<ol class="top"></ol>');
|
@@ -128,6 +171,7 @@ function generateTOC() {
|
|
128
171
|
var counter = 0;
|
129
172
|
var tags = ['h2', 'h3', 'h4', 'h5', 'h6'];
|
130
173
|
var i;
|
174
|
+
var curli;
|
131
175
|
if ($('#filecontents h1').length > 1) tags.unshift('h1');
|
132
176
|
for (i = 0; i < tags.length; i++) { tags[i] = '#filecontents ' + tags[i]; }
|
133
177
|
var lastTag = parseInt(tags[0][1], 10);
|
@@ -147,15 +191,25 @@ function generateTOC() {
|
|
147
191
|
}
|
148
192
|
if (thisTag > lastTag) {
|
149
193
|
for (i = 0; i < thisTag - lastTag; i++) {
|
150
|
-
|
194
|
+
if ( typeof(curli) == "undefined" ) {
|
195
|
+
curli = $('<li/>');
|
196
|
+
toc.append(curli);
|
197
|
+
}
|
198
|
+
toc = $('<ol/>');
|
199
|
+
curli.append(toc);
|
200
|
+
curli = undefined;
|
151
201
|
}
|
152
202
|
}
|
153
203
|
if (thisTag < lastTag) {
|
154
|
-
for (i = 0; i < lastTag - thisTag; i++)
|
204
|
+
for (i = 0; i < lastTag - thisTag; i++) {
|
205
|
+
toc = toc.parent();
|
206
|
+
toc = toc.parent();
|
207
|
+
}
|
155
208
|
}
|
156
209
|
var title = $(this).attr('toc-title');
|
157
210
|
if (typeof(title) == "undefined") title = $(this).text();
|
158
|
-
|
211
|
+
curli =$('<li><a href="#' + this.id + '">' + title + '</a></li>');
|
212
|
+
toc.append(curli);
|
159
213
|
lastTag = thisTag;
|
160
214
|
});
|
161
215
|
if (!show) return;
|
@@ -232,6 +286,16 @@ function mainFocus() {
|
|
232
286
|
setTimeout(function() { $('#main').focus(); }, 10);
|
233
287
|
}
|
234
288
|
|
289
|
+
function navigationChange() {
|
290
|
+
// This works around the broken anchor navigation with the YARD template.
|
291
|
+
window.onpopstate = function() {
|
292
|
+
var hash = window.location.hash;
|
293
|
+
if (hash !== '' && $(hash)[0]) {
|
294
|
+
$(hash)[0].scrollIntoView();
|
295
|
+
}
|
296
|
+
};
|
297
|
+
}
|
298
|
+
|
235
299
|
$(document).ready(function() {
|
236
300
|
navResizer();
|
237
301
|
navExpander();
|
@@ -241,8 +305,10 @@ $(document).ready(function() {
|
|
241
305
|
searchFrameButtons();
|
242
306
|
linkSummaries();
|
243
307
|
summaryToggle();
|
308
|
+
constantSummaryToggle();
|
244
309
|
generateTOC();
|
245
310
|
mainFocus();
|
311
|
+
navigationChange();
|
246
312
|
});
|
247
313
|
|
248
314
|
})();
|
data/docs/method_list.html
CHANGED
@@ -4,9 +4,9 @@
|
|
4
4
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
5
5
|
<meta charset="utf-8" />
|
6
6
|
|
7
|
-
<link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen"
|
7
|
+
<link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" />
|
8
8
|
|
9
|
-
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen"
|
9
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" />
|
10
10
|
|
11
11
|
|
12
12
|
|
@@ -54,13 +54,21 @@
|
|
54
54
|
|
55
55
|
<li class="even ">
|
56
56
|
<div class="item">
|
57
|
-
<span class='object_link'><a href="EnvParser.html#
|
57
|
+
<span class='object_link'><a href="EnvParser.html#autoregister-class_method" title="EnvParser.autoregister (method)">autoregister</a></span>
|
58
58
|
<small>EnvParser</small>
|
59
59
|
</div>
|
60
60
|
</li>
|
61
61
|
|
62
62
|
|
63
63
|
<li class="odd ">
|
64
|
+
<div class="item">
|
65
|
+
<span class='object_link'><a href="EnvParser.html#define_type-class_method" title="EnvParser.define_type (method)">define_type</a></span>
|
66
|
+
<small>EnvParser</small>
|
67
|
+
</div>
|
68
|
+
</li>
|
69
|
+
|
70
|
+
|
71
|
+
<li class="even ">
|
64
72
|
<div class="item">
|
65
73
|
<span class='object_link'><a href="top-level-namespace.html#filename-instance_method" title="#filename (method)">#filename</a></span>
|
66
74
|
<small>Top Level Namespace</small>
|
@@ -68,7 +76,7 @@
|
|
68
76
|
</li>
|
69
77
|
|
70
78
|
|
71
|
-
<li class="
|
79
|
+
<li class="odd ">
|
72
80
|
<div class="item">
|
73
81
|
<span class='object_link'><a href="EnvParser.html#parse-class_method" title="EnvParser.parse (method)">parse</a></span>
|
74
82
|
<small>EnvParser</small>
|
@@ -76,7 +84,7 @@
|
|
76
84
|
</li>
|
77
85
|
|
78
86
|
|
79
|
-
<li class="
|
87
|
+
<li class="even ">
|
80
88
|
<div class="item">
|
81
89
|
<span class='object_link'><a href="EnvParser.html#register-class_method" title="EnvParser.register (method)">register</a></span>
|
82
90
|
<small>EnvParser</small>
|
@@ -6,15 +6,15 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Documentation by YARD 0.9.
|
9
|
+
— Documentation by YARD 0.9.26
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
13
|
-
<link rel="stylesheet" href="css/style.css" type="text/css"
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
14
|
|
15
|
-
<link rel="stylesheet" href="css/common.css" type="text/css"
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
16
|
|
17
|
-
<script type="text/javascript"
|
17
|
+
<script type="text/javascript">
|
18
18
|
pathId = "";
|
19
19
|
relpath = '';
|
20
20
|
</script>
|
@@ -162,12 +162,12 @@
|
|
162
162
|
<pre class="lines">
|
163
163
|
|
164
164
|
|
165
|
-
|
165
|
+
3</pre>
|
166
166
|
</td>
|
167
167
|
<td>
|
168
|
-
<pre class="code"><span class="info file"># File 'lib/env_parser.rb', line
|
168
|
+
<pre class="code"><span class="info file"># File 'lib/env_parser/types.rb', line 3</span>
|
169
169
|
|
170
|
-
<span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='const'>File</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='lparen'>(</span><span class='id identifier rubyid___dir__'>__dir__</span><span class='comma'>,</span> <span class='
|
170
|
+
<span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='const'>File</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='lparen'>(</span><span class='id identifier rubyid___dir__'>__dir__</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>types</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>*.rb</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_each'>each</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_filename'>filename</span><span class='op'>|</span> <span class='id identifier rubyid_require_relative'>require_relative</span> <span class='id identifier rubyid_filename'>filename</span> <span class='rbrace'>}</span></pre>
|
171
171
|
</td>
|
172
172
|
</tr>
|
173
173
|
</table>
|
@@ -178,9 +178,9 @@
|
|
178
178
|
</div>
|
179
179
|
|
180
180
|
<div id="footer">
|
181
|
-
Generated on
|
181
|
+
Generated on Sat Jan 2 17:31:17 2021 by
|
182
182
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
183
|
-
0.9.
|
183
|
+
0.9.26 (ruby-2.7.2).
|
184
184
|
</div>
|
185
185
|
|
186
186
|
</div>
|
data/env_parser.gemspec
CHANGED
@@ -20,10 +20,14 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.add_development_dependency 'bundler', '~>
|
24
|
-
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
25
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
26
|
spec.add_development_dependency 'rspec_junit_formatter'
|
27
|
+
spec.add_development_dependency 'rubocop', '1.7'
|
28
|
+
spec.add_development_dependency 'yard'
|
27
29
|
|
28
30
|
spec.add_dependency 'activesupport', '>= 5.0.0'
|
31
|
+
spec.add_dependency 'chronic'
|
32
|
+
spec.add_dependency 'chronic_duration'
|
29
33
|
end
|
data/lib/env_parser.rb
CHANGED
@@ -1,61 +1,52 @@
|
|
1
|
+
require 'env_parser/errors'
|
1
2
|
require 'env_parser/version'
|
2
3
|
require 'active_support/all'
|
4
|
+
require 'psych'
|
3
5
|
|
4
6
|
## The EnvParser class simplifies parsing of environment variables as different data types.
|
5
7
|
##
|
6
8
|
class EnvParser
|
7
|
-
##
|
9
|
+
## The default filename to use for {.autoregister} requests.
|
8
10
|
##
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
## Exception class used to indicate parsed values not allowed per a "from_set" option.
|
13
|
-
##
|
14
|
-
class ValueNotAllowed < Error
|
15
|
-
end
|
16
|
-
|
17
|
-
## Exception class used to indicate a type has already been defined.
|
18
|
-
##
|
19
|
-
class TypeAlreadyDefined < Error
|
20
|
-
end
|
11
|
+
AUTOREGISTER_FILE = '.env_parser.yml'.freeze
|
21
12
|
|
22
13
|
class << self
|
23
|
-
## Defines a new type for use as the "as" option on a subsequent
|
14
|
+
## Defines a new type for use as the "as" option on a subsequent {.parse} or {.register} call.
|
24
15
|
##
|
25
16
|
## @param name [Symbol]
|
26
17
|
## The name to assign to the type.
|
27
18
|
##
|
28
|
-
## @option options
|
19
|
+
## @option options [Array<Symbol>] aliases
|
29
20
|
## An array of additional names you'd like to see refer to this same type.
|
30
21
|
##
|
31
|
-
## @option options if_unset
|
22
|
+
## @option options if_unset (nil)
|
32
23
|
## Specifies a "sensible default" to return for this type if the value being parsed (via
|
33
|
-
##
|
34
|
-
## overridden by the user via the
|
24
|
+
## {.parse} or {.register}) is either unset (`nil`) or blank (`''`). Note this may be
|
25
|
+
## overridden by the user via the {.parse}/{.register} "if_unset" option.
|
35
26
|
##
|
36
|
-
## @yield
|
27
|
+
## @yield [value]
|
37
28
|
## A block to act as the parser for the this type. If no block is given, an ArgumentError is
|
38
29
|
## raised.
|
39
30
|
##
|
40
|
-
## When the type defined is used via a
|
31
|
+
## When the type defined is used via a {.parse}/{.register} call, this block is invoked with
|
41
32
|
## the value to be parsed. Said value is guaranteed to be a non-empty String (the "if_unset"
|
42
33
|
## check will have already run), but no other assurances as to content are given. The block
|
43
34
|
## should return the final output of parsing the given String value as the type being defined.
|
44
35
|
##
|
45
36
|
## If the value given cannot be sensibly parsed into the type defined, the block should raise
|
46
|
-
## an EnvParser::
|
37
|
+
## an {EnvParser::ValueNotConvertibleError}.
|
47
38
|
##
|
48
39
|
## @return [nil]
|
49
40
|
## This generates no usable value.
|
50
41
|
##
|
51
|
-
## @raise [ArgumentError, EnvParser::
|
42
|
+
## @raise [ArgumentError, EnvParser::TypeAlreadyDefinedError]
|
52
43
|
##
|
53
44
|
def define_type(name, options = {}, &parser)
|
54
45
|
raise(ArgumentError, 'no parsing block given') unless block_given?
|
55
46
|
|
56
47
|
given_types = (Array(name) + Array(options[:aliases])).map(&:to_s).map(&:to_sym)
|
57
48
|
given_types.each do |type|
|
58
|
-
raise(
|
49
|
+
raise(TypeAlreadyDefinedError, "cannot redefine #{type.inspect}") if known_types.key?(type)
|
59
50
|
|
60
51
|
known_types[type] = {
|
61
52
|
parser: parser,
|
@@ -72,12 +63,13 @@ class EnvParser
|
|
72
63
|
## The value to parse/interpret. If a String is given, the value will be used as-is. If a
|
73
64
|
## Symbol is given, the ENV value for the matching string key will be used.
|
74
65
|
##
|
75
|
-
## @option options
|
66
|
+
## @option options [Symbol] as
|
76
67
|
## The expected return type. A best-effort attempt is made to convert the source String to the
|
77
68
|
## requested type.
|
78
69
|
##
|
79
|
-
## If no "as" option is given
|
80
|
-
##
|
70
|
+
## If no "as" option is given, an ArgumentError is raised. If the "as" option given is unknown
|
71
|
+
## (the given type has not been previously defined via {.define_type}), an
|
72
|
+
## {EnvParser::UnknownTypeError} is raised.
|
81
73
|
##
|
82
74
|
## @option options if_unset
|
83
75
|
## Specifies the default value to return if the given "value" is either unset (`nil`) or blank
|
@@ -85,43 +77,45 @@ class EnvParser
|
|
85
77
|
## change having been made. If unspecified, the "default" value for `nil`/`''` input will
|
86
78
|
## depend on the "as" type.
|
87
79
|
##
|
88
|
-
## @option options
|
80
|
+
## @option options [Array, Range] from_set
|
89
81
|
## Gives a limited set of allowed values (after type conversion). If, after parsing, the final
|
90
|
-
## value is not included in the "from_set" list/range, an EnvParser::
|
91
|
-
##
|
82
|
+
## value is not included in the "from_set" list/range, an {EnvParser::ValueNotAllowedError} is
|
83
|
+
## raised.
|
92
84
|
##
|
93
85
|
## Note that if the "if_unset" option is given and the value to parse is `nil`/`''`, the
|
94
86
|
## "if_unset" value will be returned, even if it is not part of the "from_set" list/range.
|
95
87
|
##
|
96
88
|
## Also note that, due to the nature of the lookup, the "from_set" option is only available
|
97
89
|
## for scalar values (i.e. not arrays, hashes, or other enumerables). An attempt to use the
|
98
|
-
## "from_set" option with a non-scalar value will raise an ArgumentError
|
90
|
+
## "from_set" option with a non-scalar value will raise an ArgumentError.
|
99
91
|
##
|
100
|
-
## @option options
|
101
|
-
## If given, the "validated_by"
|
92
|
+
## @option options [Proc] validated_by
|
93
|
+
## If given, the "validated_by" Proc is called with the parsed value (after type conversion)
|
102
94
|
## as its sole argument. This allows for user-defined validation of the parsed value beyond
|
103
|
-
## what can be enforced by use of the "from_set" option alone. If the
|
104
|
-
## `#blank?`, an EnvParser::
|
105
|
-
## choice, this validation
|
95
|
+
## what can be enforced by use of the "from_set" option alone. If the Proc's return value is
|
96
|
+
## `#blank?`, an {EnvParser::ValueNotAllowedError} is raised. To accomodate your syntax of
|
97
|
+
## choice, this validation Proc may be given as a block instead.
|
106
98
|
##
|
107
99
|
## Note that this option is intended to provide an inspection mechanism only -- no mutation
|
108
|
-
## of the parsed value should occur within the given
|
100
|
+
## of the parsed value should occur within the given Proc. To that end, the argument passed is
|
109
101
|
## a *frozen* duplicate of the parsed value.
|
110
102
|
##
|
111
103
|
## @yield [value]
|
112
|
-
## A block (if given) is treated exactly as the "validated_by" Proc would.
|
113
|
-
## no compelling reason to provide both a "validated_by" proc *and* a validation block, there
|
114
|
-
## is no technical limitation preventing this. **If both are given, both validation checks
|
115
|
-
## must pass.**
|
104
|
+
## A block (if given) is treated exactly as the "validated_by" Proc would.
|
116
105
|
##
|
117
|
-
##
|
106
|
+
## Although there is no compelling reason to provide both a "validated_by" Proc *and* a
|
107
|
+
## validation block, there is no technical limitation preventing this. **If both are given,
|
108
|
+
## both validation checks must pass.**
|
109
|
+
##
|
110
|
+
## @raise [ArgumentError, EnvParser::UnknownTypeError, EnvParser::ValueNotAllowedError]
|
118
111
|
##
|
119
112
|
def parse(value, options = {}, &validation_block)
|
120
113
|
value = ENV[value.to_s] if value.is_a? Symbol
|
121
114
|
value = value.to_s
|
122
115
|
|
123
116
|
type = known_types[options[:as]]
|
124
|
-
raise(ArgumentError,
|
117
|
+
raise(ArgumentError, 'missing `as` parameter') unless options.key?(:as)
|
118
|
+
raise(UnknownTypeError, "invalid `as` parameter: #{options[:as].inspect}") unless type
|
125
119
|
|
126
120
|
return (options.key?(:if_unset) ? options[:if_unset] : type[:if_unset]) if value.blank?
|
127
121
|
|
@@ -134,9 +128,8 @@ class EnvParser
|
|
134
128
|
|
135
129
|
## Parses the referenced value and creates a matching constant in the requested context.
|
136
130
|
##
|
137
|
-
## Multiple calls to
|
138
|
-
##
|
139
|
-
## "register" call.
|
131
|
+
## Multiple calls to {.register} may be shortcutted by passing in a Hash whose keys are the
|
132
|
+
## variable names and whose values are the options set for each variable's {.register} call.
|
140
133
|
##
|
141
134
|
## <pre>
|
142
135
|
## ## Example shortcut usage:
|
@@ -153,40 +146,39 @@ class EnvParser
|
|
153
146
|
## </pre>
|
154
147
|
##
|
155
148
|
## @param name
|
156
|
-
## The name of the value to parse/interpret from the "from" Hash. If the "from" value is
|
157
|
-
## you may give a Symbol and the corresponding String key will be used instead.
|
149
|
+
## The name of the value to parse/interpret from the "from" Hash. If the "from" value is
|
150
|
+
## `ENV`, you may give a Symbol and the corresponding String key will be used instead.
|
158
151
|
##
|
159
|
-
## @option options
|
160
|
-
## The source Hash from which to pull the value referenced by the "name" key.
|
152
|
+
## @option options [Hash] from (ENV)
|
153
|
+
## The source Hash from which to pull the value referenced by the "name" key.
|
161
154
|
##
|
162
|
-
## @option options
|
163
|
-
## The module or class in which the constant should be created.
|
164
|
-
##
|
155
|
+
## @option options [Module, Class] within (Kernel)
|
156
|
+
## The module or class in which the constant should be created. Creates global constants by
|
157
|
+
## default.
|
165
158
|
##
|
166
|
-
## @option options
|
167
|
-
## See
|
159
|
+
## @option options [Symbol] as
|
160
|
+
## See {.parse}.
|
168
161
|
##
|
169
162
|
## @option options if_unset
|
170
|
-
## See
|
163
|
+
## See {.parse}.
|
171
164
|
##
|
172
|
-
## @option options
|
173
|
-
## See
|
165
|
+
## @option options [Array, Range] from_set
|
166
|
+
## See {.parse}.
|
174
167
|
##
|
175
|
-
## @option options
|
176
|
-
## See
|
168
|
+
## @option options [Proc] validated_by
|
169
|
+
## See {.parse}.
|
177
170
|
##
|
178
171
|
## @yield [value]
|
179
|
-
## A block (if given) is treated exactly as in
|
180
|
-
##
|
181
|
-
## validation must give its own "validated_by"
|
172
|
+
## A block (if given) is treated exactly as in {.parse}. Note, however, that a single block
|
173
|
+
## cannot be used to register multiple constants simultaneously -- each value needing
|
174
|
+
## validation must give its own "validated_by" Proc.
|
182
175
|
##
|
183
176
|
## @raise [ArgumentError]
|
184
177
|
##
|
185
178
|
def register(name, options = {}, &validation_block)
|
186
|
-
##
|
187
|
-
## method call.
|
179
|
+
## Allow for registering multiple variables simultaneously via a single call.
|
188
180
|
if name.is_a? Hash
|
189
|
-
raise
|
181
|
+
raise(ArgumentError, 'cannot register multiple values with one block') if block_given?
|
190
182
|
return register_all(name)
|
191
183
|
end
|
192
184
|
|
@@ -202,9 +194,7 @@ class EnvParser
|
|
202
194
|
name = name.to_s
|
203
195
|
end
|
204
196
|
|
205
|
-
unless from.is_a?
|
206
|
-
raise ArgumentError, "invalid `from` parameter: #{from.class}"
|
207
|
-
end
|
197
|
+
raise ArgumentError, "invalid `from` parameter: #{from.class}" unless from.is_a? Hash
|
208
198
|
|
209
199
|
unless within.is_a?(Module) || within.is_a?(Class)
|
210
200
|
raise ArgumentError, "invalid `within` parameter: #{within.inspect}"
|
@@ -217,14 +207,14 @@ class EnvParser
|
|
217
207
|
value
|
218
208
|
end
|
219
209
|
|
220
|
-
## Creates ENV bindings for
|
210
|
+
## Creates ENV bindings for {.parse} and {.register} proxy methods.
|
221
211
|
##
|
222
212
|
## The sole difference between these proxy methods and their EnvParser counterparts is that
|
223
213
|
## ENV.parse will interpret any value given as an ENV key (as a String), not the given value
|
224
214
|
## itself. i.e. ENV.parse('XYZ', ...) is equivalent to EnvParser.parse(ENV['XYZ'], ...)
|
225
215
|
##
|
226
216
|
## @return [ENV]
|
227
|
-
## This generates no usable value
|
217
|
+
## This generates no usable value.
|
228
218
|
##
|
229
219
|
def add_env_bindings
|
230
220
|
ENV.instance_eval do
|
@@ -240,6 +230,47 @@ class EnvParser
|
|
240
230
|
ENV
|
241
231
|
end
|
242
232
|
|
233
|
+
## Reads an "autoregister" file and registers the ENV constants defined therein.
|
234
|
+
##
|
235
|
+
## The "autoregister" file is read, parsed as YAML, sanitized for use as a parameter to
|
236
|
+
## {.register_all}, and then passed along for processing. The return value from that
|
237
|
+
## {.register_all} call is passed through.
|
238
|
+
##
|
239
|
+
## @param filename [String]
|
240
|
+
## A path for the autoregister file to parse and process. Defaults to
|
241
|
+
## {EnvParser::AUTOREGISTER_FILE} if unset.
|
242
|
+
##
|
243
|
+
## @return [Hash]
|
244
|
+
## The return value from the {.register_all} call that handles the actual registration.
|
245
|
+
##
|
246
|
+
## @raise [EnvParser::AutoregisterFileNotFound, EnvParser::UnparseableAutoregisterSpec]
|
247
|
+
##
|
248
|
+
def autoregister(filename = nil)
|
249
|
+
filename ||= AUTOREGISTER_FILE
|
250
|
+
autoregister_spec = Psych.load_file(filename)
|
251
|
+
|
252
|
+
autoregister_spec.deep_symbolize_keys!
|
253
|
+
autoregister_spec.transform_values! do |spec|
|
254
|
+
sanitized = spec.slice(:as, :within, :if_unset, :from_set)
|
255
|
+
sanitized[:as] = sanitized[:as].to_sym if sanitized.key? :as
|
256
|
+
sanitized[:within] = sanitized[:within].constantize if sanitized.key? :within
|
257
|
+
|
258
|
+
sanitized
|
259
|
+
end
|
260
|
+
|
261
|
+
register_all autoregister_spec
|
262
|
+
|
263
|
+
## Psych raises an Errno::ENOENT on file-not-found.
|
264
|
+
##
|
265
|
+
rescue Errno::ENOENT
|
266
|
+
raise EnvParser::AutoregisterFileNotFound, %(file not found: "#{filename}")
|
267
|
+
|
268
|
+
## Psych raises a Psych::SyntaxError on unparseable YAML.
|
269
|
+
##
|
270
|
+
rescue Psych::SyntaxError => e
|
271
|
+
raise EnvParser::UnparseableAutoregisterSpec, "malformed YAML in spec file: #{e.message}"
|
272
|
+
end
|
273
|
+
|
243
274
|
private
|
244
275
|
|
245
276
|
## Class instance variable for storing known type data.
|
@@ -256,7 +287,7 @@ class EnvParser
|
|
256
287
|
## @return [nil]
|
257
288
|
## This generates no usable value.
|
258
289
|
##
|
259
|
-
## @raise [ArgumentError, EnvParser::
|
290
|
+
## @raise [ArgumentError, EnvParser::ValueNotAllowedError]
|
260
291
|
##
|
261
292
|
def check_for_set_inclusion(value, set: nil)
|
262
293
|
if value.respond_to?(:each)
|
@@ -267,9 +298,7 @@ class EnvParser
|
|
267
298
|
raise ArgumentError, "invalid `from_set` parameter type: #{set.class}"
|
268
299
|
end
|
269
300
|
|
270
|
-
raise
|
271
|
-
|
272
|
-
nil
|
301
|
+
raise(ValueNotAllowedError, 'parsed value not in allowed set') unless set.include?(value)
|
273
302
|
end
|
274
303
|
|
275
304
|
## Verifies that the given "value" passes both the "proc" and "block" validations.
|
@@ -281,18 +310,17 @@ class EnvParser
|
|
281
310
|
## @return [nil]
|
282
311
|
## This generates no usable value.
|
283
312
|
##
|
284
|
-
## @raise [EnvParser::
|
313
|
+
## @raise [EnvParser::ValueNotAllowedError]
|
285
314
|
##
|
286
315
|
def check_user_defined_validations(value, proc: nil, block: nil)
|
287
316
|
immutable_value = value.dup.freeze
|
288
|
-
|
289
|
-
raise ValueNotAllowed, error unless [proc, block].compact.all? { |i| i.call(immutable_value) }
|
317
|
+
all_tests_passed = [proc, block].compact.all? { |i| i.call(immutable_value) }
|
290
318
|
|
291
|
-
|
319
|
+
raise(ValueNotAllowedError, 'parsed value failed user validation') unless all_tests_passed
|
292
320
|
end
|
293
321
|
|
294
|
-
## Receives a list of
|
295
|
-
## values being each
|
322
|
+
## Receives a list of {.register} calls to make, as a Hash keyed with variable names and the
|
323
|
+
## values being each {.register} call's option set.
|
296
324
|
##
|
297
325
|
## @param list [Hash]
|
298
326
|
##
|
@@ -301,7 +329,7 @@ class EnvParser
|
|
301
329
|
## @raise [ArgumentError]
|
302
330
|
##
|
303
331
|
def register_all(list)
|
304
|
-
raise
|
332
|
+
raise(ArgumentError, "invalid 'list' parameter type: #{list.class}") unless list.is_a? Hash
|
305
333
|
|
306
334
|
list.to_a.each_with_object({}) do |tuple, output|
|
307
335
|
output[tuple.first] = register(tuple.first, tuple.second)
|
@@ -310,6 +338,6 @@ class EnvParser
|
|
310
338
|
end
|
311
339
|
end
|
312
340
|
|
313
|
-
## Load
|
341
|
+
## Load predefined types.
|
314
342
|
##
|
315
|
-
|
343
|
+
require 'env_parser/types'
|