env_parser 0.8.0 → 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.
@@ -82,6 +82,8 @@
82
82
  <p class="children">
83
83
 
84
84
 
85
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="EnvParserTypes.html" title="EnvParserTypes (module)">EnvParserTypes</a></span>
86
+
85
87
 
86
88
 
87
89
  <strong class="classes">Classes:</strong> <span class='object_link'><a href="EnvParser.html" title="EnvParser (class)">EnvParser</a></span>
@@ -162,12 +164,12 @@
162
164
  <pre class="lines">
163
165
 
164
166
 
165
- 315</pre>
167
+ 3</pre>
166
168
  </td>
167
169
  <td>
168
- <pre class="code"><span class="info file"># File 'lib/env_parser.rb', line 315</span>
170
+ <pre class="code"><span class="info file"># File 'lib/env_parser/types.rb', line 3</span>
169
171
 
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='qwords_beg'>%w[</span><span class='tstring_content'>env_parser</span><span class='words_sep'> </span><span class='tstring_content'>types</span><span class='words_sep'> </span><span class='tstring_content'>*.rb</span><span class='words_sep'>]</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>
172
+ <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'>&#39;</span><span class='tstring_content'>types</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>*.rb</span><span class='tstring_end'>&#39;</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
173
  </td>
172
174
  </tr>
173
175
  </table>
@@ -178,7 +180,7 @@
178
180
  </div>
179
181
 
180
182
  <div id="footer">
181
- Generated on Sun Dec 24 19:33:35 2017 by
183
+ Generated on Mon Dec 25 19:13:02 2017 by
182
184
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
183
185
  0.9.11 (ruby-2.4.2).
184
186
  </div>
@@ -1,61 +1,47 @@
1
+ require 'env_parser/errors'
1
2
  require 'env_parser/version'
2
3
  require 'active_support/all'
3
4
 
4
5
  ## The EnvParser class simplifies parsing of environment variables as different data types.
5
6
  ##
6
7
  class EnvParser
7
- ## Base exception class for EnvParser.
8
- ##
9
- class Error < ::StandardError
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
21
-
22
8
  class << self
23
- ## Defines a new type for use as the "as" option on a subsequent `.parse` or `.register` call.
9
+ ## Defines a new type for use as the "as" option on a subsequent {.parse} or {.register} call.
24
10
  ##
25
11
  ## @param name [Symbol]
26
12
  ## The name to assign to the type.
27
13
  ##
28
- ## @option options aliases [Array<Symbol>]
14
+ ## @option options [Array<Symbol>] aliases
29
15
  ## An array of additional names you'd like to see refer to this same type.
30
16
  ##
31
- ## @option options if_unset
17
+ ## @option options if_unset (nil)
32
18
  ## Specifies a "sensible default" to return for this type if the value being parsed (via
33
- ## `.parse` or `.register`) is either unset (`nil`) or blank (`''`). Note this may be
34
- ## overridden by the user via the `.parse`/`.register` "if_unset" option.
19
+ ## {.parse} or {.register}) is either unset (`nil`) or blank (`''`). Note this may be
20
+ ## overridden by the user via the {.parse}/{.register} "if_unset" option.
35
21
  ##
36
- ## @yield
22
+ ## @yield [value]
37
23
  ## A block to act as the parser for the this type. If no block is given, an ArgumentError is
38
24
  ## raised.
39
25
  ##
40
- ## When the type defined is used via a `.parse`/`.register` call, this block is invoked with
26
+ ## When the type defined is used via a {.parse}/{.register} call, this block is invoked with
41
27
  ## the value to be parsed. Said value is guaranteed to be a non-empty String (the "if_unset"
42
28
  ## check will have already run), but no other assurances as to content are given. The block
43
29
  ## should return the final output of parsing the given String value as the type being defined.
44
30
  ##
45
31
  ## If the value given cannot be sensibly parsed into the type defined, the block should raise
46
- ## an EnvParser::ValueNotAllowed exception.
32
+ ## an {EnvParser::ValueNotConvertibleError}.
47
33
  ##
48
34
  ## @return [nil]
49
35
  ## This generates no usable value.
50
36
  ##
51
- ## @raise [ArgumentError, EnvParser::TypeAlreadyDefined]
37
+ ## @raise [ArgumentError, EnvParser::TypeAlreadyDefinedError]
52
38
  ##
53
39
  def define_type(name, options = {}, &parser)
54
40
  raise(ArgumentError, 'no parsing block given') unless block_given?
55
41
 
56
42
  given_types = (Array(name) + Array(options[:aliases])).map(&:to_s).map(&:to_sym)
57
43
  given_types.each do |type|
58
- raise(TypeAlreadyDefined, "cannot redefine #{type.inspect}") if known_types.key?(type)
44
+ raise(TypeAlreadyDefinedError, "cannot redefine #{type.inspect}") if known_types.key?(type)
59
45
 
60
46
  known_types[type] = {
61
47
  parser: parser,
@@ -72,12 +58,13 @@ class EnvParser
72
58
  ## The value to parse/interpret. If a String is given, the value will be used as-is. If a
73
59
  ## Symbol is given, the ENV value for the matching string key will be used.
74
60
  ##
75
- ## @option options as [Symbol]
61
+ ## @option options [Symbol] as
76
62
  ## The expected return type. A best-effort attempt is made to convert the source String to the
77
63
  ## requested type.
78
64
  ##
79
- ## If no "as" option is given (or the "as" value given has not been defined), an ArgumentError
80
- ## exception is raised.
65
+ ## If no "as" option is given, an ArgumentError is raised. If the "as" option given is unknown
66
+ ## (the given type has not been previously defined via {.define_type}), an
67
+ ## {EnvParser::UnknownTypeError} is raised.
81
68
  ##
82
69
  ## @option options if_unset
83
70
  ## Specifies the default value to return if the given "value" is either unset (`nil`) or blank
@@ -85,43 +72,45 @@ class EnvParser
85
72
  ## change having been made. If unspecified, the "default" value for `nil`/`''` input will
86
73
  ## depend on the "as" type.
87
74
  ##
88
- ## @option options from_set [Array, Range]
75
+ ## @option options [Array, Range] from_set
89
76
  ## 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::ValueNotAllowed exception
91
- ## is raised.
77
+ ## value is not included in the "from_set" list/range, an {EnvParser::ValueNotAllowedError} is
78
+ ## raised.
92
79
  ##
93
80
  ## Note that if the "if_unset" option is given and the value to parse is `nil`/`''`, the
94
81
  ## "if_unset" value will be returned, even if it is not part of the "from_set" list/range.
95
82
  ##
96
83
  ## Also note that, due to the nature of the lookup, the "from_set" option is only available
97
84
  ## 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 exception.
85
+ ## "from_set" option with a non-scalar value will raise an ArgumentError.
99
86
  ##
100
- ## @option options validated_by [Proc]
101
- ## If given, the "validated_by" proc is called with the parsed value (after type conversion)
87
+ ## @option options [Proc] validated_by
88
+ ## If given, the "validated_by" Proc is called with the parsed value (after type conversion)
102
89
  ## 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 proc's return value is
104
- ## `#blank?`, an EnvParser::ValueNotAllowed exception is raised. To accomodate your syntax of
105
- ## choice, this validation proc may be given as a yield block instead.
90
+ ## what can be enforced by use of the "from_set" option alone. If the Proc's return value is
91
+ ## `#blank?`, an {EnvParser::ValueNotAllowedError} is raised. To accomodate your syntax of
92
+ ## choice, this validation Proc may be given as a block instead.
106
93
  ##
107
94
  ## Note that this option is intended to provide an inspection mechanism only -- no mutation
108
- ## of the parsed value should occur within the given proc. To that end, the argument passed is
95
+ ## of the parsed value should occur within the given Proc. To that end, the argument passed is
109
96
  ## a *frozen* duplicate of the parsed value.
110
97
  ##
111
98
  ## @yield [value]
112
- ## A block (if given) is treated exactly as the "validated_by" Proc would. Although there is
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.**
99
+ ## A block (if given) is treated exactly as the "validated_by" Proc would.
116
100
  ##
117
- ## @raise [ArgumentError, EnvParser::ValueNotAllowed]
101
+ ## Although there is no compelling reason to provide both a "validated_by" Proc *and* a
102
+ ## validation block, there is no technical limitation preventing this. **If both are given,
103
+ ## both validation checks must pass.**
104
+ ##
105
+ ## @raise [ArgumentError, EnvParser::UnknownTypeError, EnvParser::ValueNotAllowedError]
118
106
  ##
119
107
  def parse(value, options = {}, &validation_block)
120
108
  value = ENV[value.to_s] if value.is_a? Symbol
121
109
  value = value.to_s
122
110
 
123
111
  type = known_types[options[:as]]
124
- raise(ArgumentError, "invalid `as` parameter: #{options[:as].inspect}") unless type
112
+ raise(ArgumentError, 'missing `as` parameter') unless options.key?(:as)
113
+ raise(UnknownTypeError, "invalid `as` parameter: #{options[:as].inspect}") unless type
125
114
 
126
115
  return (options.key?(:if_unset) ? options[:if_unset] : type[:if_unset]) if value.blank?
127
116
 
@@ -134,9 +123,8 @@ class EnvParser
134
123
 
135
124
  ## Parses the referenced value and creates a matching constant in the requested context.
136
125
  ##
137
- ## Multiple calls to "register" may be shortcutted by passing in a Hash with the same keys as
138
- ## those in the "from" Hash and each value being the "register" options set for each variable's
139
- ## "register" call.
126
+ ## Multiple calls to {.register} may be shortcutted by passing in a Hash whose keys are the
127
+ ## variable names and whose values are the options set for each variable's {.register} call.
140
128
  ##
141
129
  ## <pre>
142
130
  ## ## Example shortcut usage:
@@ -153,40 +141,39 @@ class EnvParser
153
141
  ## </pre>
154
142
  ##
155
143
  ## @param name
156
- ## The name of the value to parse/interpret from the "from" Hash. If the "from" value is ENV,
157
- ## you may give a Symbol and the corresponding String key will be used instead.
144
+ ## The name of the value to parse/interpret from the "from" Hash. If the "from" value is
145
+ ## `ENV`, you may give a Symbol and the corresponding String key will be used instead.
158
146
  ##
159
- ## @option options from [Hash]
160
- ## The source Hash from which to pull the value referenced by the "name" key. Defaults to ENV.
147
+ ## @option options [Hash] from (ENV)
148
+ ## The source Hash from which to pull the value referenced by the "name" key.
161
149
  ##
162
- ## @option options within [Module, Class]
163
- ## The module or class in which the constant should be created. Defaults to Kernel (making it
164
- ## a global constant).
150
+ ## @option options [Module, Class] within (Kernel)
151
+ ## The module or class in which the constant should be created. Creates global constants by
152
+ ## default.
165
153
  ##
166
- ## @option options as [Symbol]
167
- ## See `.parse`.
154
+ ## @option options [Symbol] as
155
+ ## See {.parse}.
168
156
  ##
169
157
  ## @option options if_unset
170
- ## See `.parse`.
158
+ ## See {.parse}.
171
159
  ##
172
- ## @option options from_set [Array, Range]
173
- ## See `.parse`.
160
+ ## @option options [Array, Range] from_set
161
+ ## See {.parse}.
174
162
  ##
175
- ## @option options validated_by [Proc]
176
- ## See `.parse`.
163
+ ## @option options [Proc] validated_by
164
+ ## See {.parse}.
177
165
  ##
178
166
  ## @yield [value]
179
- ## A block (if given) is treated exactly as in `.parse`. Note, however, that a single yield
180
- ## block cannot be used to register multiple constants simultaneously -- each value needing
181
- ## validation must give its own "validated_by" proc.
167
+ ## A block (if given) is treated exactly as in {.parse}. Note, however, that a single block
168
+ ## cannot be used to register multiple constants simultaneously -- each value needing
169
+ ## validation must give its own "validated_by" Proc.
182
170
  ##
183
171
  ## @raise [ArgumentError]
184
172
  ##
185
173
  def register(name, options = {}, &validation_block)
186
- ## We want to allow for registering multiple variables simultaneously via a single `.register`
187
- ## method call.
174
+ ## Allow for registering multiple variables simultaneously via a single call.
188
175
  if name.is_a? Hash
189
- raise ArgumentError, 'cannot register multiple values with one yield block' if block_given?
176
+ raise(ArgumentError, 'cannot register multiple values with one block') if block_given?
190
177
  return register_all(name)
191
178
  end
192
179
 
@@ -217,14 +204,14 @@ class EnvParser
217
204
  value
218
205
  end
219
206
 
220
- ## Creates ENV bindings for EnvParser.parse and EnvParser.register proxy methods.
207
+ ## Creates ENV bindings for {.parse} and {.register} proxy methods.
221
208
  ##
222
209
  ## The sole difference between these proxy methods and their EnvParser counterparts is that
223
210
  ## ENV.parse will interpret any value given as an ENV key (as a String), not the given value
224
211
  ## itself. i.e. ENV.parse('XYZ', ...) is equivalent to EnvParser.parse(ENV['XYZ'], ...)
225
212
  ##
226
213
  ## @return [ENV]
227
- ## This generates no usable value, so we may as well return ENV for chaining?
214
+ ## This generates no usable value.
228
215
  ##
229
216
  def add_env_bindings
230
217
  ENV.instance_eval do
@@ -256,7 +243,7 @@ class EnvParser
256
243
  ## @return [nil]
257
244
  ## This generates no usable value.
258
245
  ##
259
- ## @raise [ArgumentError, EnvParser::ValueNotAllowed]
246
+ ## @raise [ArgumentError, EnvParser::ValueNotAllowedError]
260
247
  ##
261
248
  def check_for_set_inclusion(value, set: nil)
262
249
  if value.respond_to?(:each)
@@ -267,7 +254,7 @@ class EnvParser
267
254
  raise ArgumentError, "invalid `from_set` parameter type: #{set.class}"
268
255
  end
269
256
 
270
- raise ValueNotAllowed, 'parsed value not in allowed list/range' unless set.include?(value)
257
+ raise(ValueNotAllowedError, 'parsed value not in allowed set') unless set.include?(value)
271
258
 
272
259
  nil
273
260
  end
@@ -281,18 +268,18 @@ class EnvParser
281
268
  ## @return [nil]
282
269
  ## This generates no usable value.
283
270
  ##
284
- ## @raise [EnvParser::ValueNotAllowed]
271
+ ## @raise [EnvParser::ValueNotAllowedError]
285
272
  ##
286
273
  def check_user_defined_validations(value, proc: nil, block: nil)
287
274
  immutable_value = value.dup.freeze
288
- error = 'parsed value failed user validation'
289
- raise ValueNotAllowed, error unless [proc, block].compact.all? { |i| i.call(immutable_value) }
275
+ all_tests_passed = [proc, block].compact.all? { |i| i.call(immutable_value) }
276
+ raise(ValueNotAllowedError, 'parsed value failed user validation') unless all_tests_passed
290
277
 
291
278
  nil
292
279
  end
293
280
 
294
- ## Receives a list of "register" calls to make, as a Hash keyed with variable names and the
295
- ## values being each "register" call's option set.
281
+ ## Receives a list of {.register} calls to make, as a Hash keyed with variable names and the
282
+ ## values being each {.register} call's option set.
296
283
  ##
297
284
  ## @param list [Hash]
298
285
  ##
@@ -301,7 +288,7 @@ class EnvParser
301
288
  ## @raise [ArgumentError]
302
289
  ##
303
290
  def register_all(list)
304
- raise ArgumentError, "invalid 'list' parameter type: #{list.class}" unless list.is_a?(Hash)
291
+ raise(ArgumentError, "invalid 'list' parameter type: #{list.class}") unless list.is_a?(Hash)
305
292
 
306
293
  list.to_a.each_with_object({}) do |tuple, output|
307
294
  output[tuple.first] = register(tuple.first, tuple.second)
@@ -310,6 +297,6 @@ class EnvParser
310
297
  end
311
298
  end
312
299
 
313
- ## Load all files listed in "/lib/env_parser/types".
300
+ ## Load predefined types.
314
301
  ##
315
- Dir.glob(File.join(__dir__, %w[env_parser types *.rb])).each { |filename| require_relative filename }
302
+ require 'env_parser/types'
@@ -0,0 +1,28 @@
1
+ class EnvParser
2
+ ## Base error class for EnvParser.
3
+ ##
4
+ class Error < ::StandardError
5
+ end
6
+
7
+ ## Error class used to indicate a type has already been defined.
8
+ ##
9
+ class TypeAlreadyDefinedError < Error
10
+ end
11
+
12
+ ## Error class used to indicate the requested "as" type has not been defined.
13
+ ##
14
+ class UnknownTypeError < Error
15
+ end
16
+
17
+ ## Error class used to indicate value given is not convertible to the requested type.
18
+ ##
19
+ class ValueNotConvertibleError < Error
20
+ end
21
+
22
+ ## Error class used to indicate parsed values that do not pass user-validation, either by not
23
+ ## being part of the given "from_set" list, or by failing the "validated_by" Proc or yield-block
24
+ ## check.
25
+ ##
26
+ class ValueNotAllowedError < Error
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ ## Load all files listed in "/lib/env_parser/types".
2
+ ##
3
+ Dir.glob(File.join(__dir__, 'types', '*.rb')).each { |filename| require_relative filename }
@@ -1,39 +1,93 @@
1
1
  require 'env_parser'
2
2
 
3
- EnvParser.define_type(:string, if_unset: '') do |value|
4
- value
5
- end
3
+ ## The parent module for all EnvParser type definition modules.
4
+ ## Exists only for documentation's sake.
5
+ ##
6
+ module EnvParserTypes
7
+ ## Defines types for primitive classes, adding the following:
8
+ ##
9
+ ## <table>
10
+ ## <tbody>
11
+ ## <tr>
12
+ ## <th><code>:as</code> value</th>
13
+ ## <th>type returned</th>
14
+ ## </tr>
15
+ ## </tbody>
16
+ ## <tbody>
17
+ ## <tr>
18
+ ## <td>:string</td>
19
+ ## <td>String</td>
20
+ ## </tr>
21
+ ## <tr>
22
+ ## <td>:symbol</td>
23
+ ## <td>Symbol</td>
24
+ ## </tr>
25
+ ## <tr>
26
+ ## <td>:boolean</td>
27
+ ## <td>TrueValue / FalseValue</td>
28
+ ## </tr>
29
+ ## <tr>
30
+ ## <td>:int / :integer</td>
31
+ ## <td>Integer</td>
32
+ ## </tr>
33
+ ## <tr>
34
+ ## <td>:float / :decimal / :number</td>
35
+ ## <td>Float</td>
36
+ ## </tr>
37
+ ## <tr>
38
+ ## <td>:json</td>
39
+ ## <td>&lt; depends on JSON given &gt;</td>
40
+ ## </tr>
41
+ ## <tr>
42
+ ## <td>:array</td>
43
+ ## <td>Array</td>
44
+ ## </tr>
45
+ ## <tr>
46
+ ## <td>:hash</td>
47
+ ## <td>Hash</td>
48
+ ## </tr>
49
+ ## </tbody>
50
+ ## </table>
51
+ ##
52
+ ## Note JSON is parsed using *quirks-mode* (meaning 'true', '25', and 'null' are all considered valid, parseable JSON).
53
+ ##
54
+ module BaseTypes
55
+ EnvParser.define_type(:string, if_unset: '') do |value|
56
+ value
57
+ end
6
58
 
7
- EnvParser.define_type(:symbol, if_unset: :'', &:to_sym)
59
+ EnvParser.define_type(:symbol, if_unset: :'', &:to_sym)
8
60
 
9
- EnvParser.define_type(:boolean, if_unset: false) do |value|
10
- case value
11
- when '', '0', 'f', 'false' then false
12
- else true
13
- end
14
- end
61
+ EnvParser.define_type(:boolean, if_unset: false) do |value|
62
+ case value
63
+ when '', '0', 'f', 'false' then false
64
+ else true
65
+ end
66
+ end
15
67
 
16
- EnvParser.define_type(:integer, aliases: %i[int], if_unset: 0, &:to_i)
68
+ EnvParser.define_type(:integer, aliases: %i[int], if_unset: 0, &:to_i)
17
69
 
18
- EnvParser.define_type(:float, aliases: %i[decimal number], if_unset: 0.0, &:to_f)
70
+ EnvParser.define_type(:float, aliases: %i[decimal number], if_unset: 0.0, &:to_f)
19
71
 
20
- EnvParser.define_type(:json, if_unset: nil) do |value|
21
- require 'json'
72
+ EnvParser.define_type(:json, if_unset: nil) do |value|
73
+ require 'json'
22
74
 
23
- decoded_json = JSON.parse(value, quirks_mode: true)
24
- { decoded_json: decoded_json }.with_indifferent_access[:decoded_json]
25
- end
75
+ decoded_json = JSON.parse(value, quirks_mode: true)
76
+ { decoded_json: decoded_json }.with_indifferent_access[:decoded_json]
77
+ end
26
78
 
27
- EnvParser.define_type(:array, if_unset: []) do |value|
28
- decoded_json = EnvParser.parse(value, as: :json)
29
- raise(ArgumentError, 'non-array value') unless decoded_json.is_a? Array
79
+ EnvParser.define_type(:array, if_unset: []) do |value|
80
+ decoded_json = EnvParser.parse(value, as: :json)
81
+ raise(EnvParser::ValueNotConvertibleError, 'non-array value') unless decoded_json.is_a? Array
30
82
 
31
- decoded_json
32
- end
83
+ decoded_json
84
+ end
33
85
 
34
- EnvParser.define_type(:hash, if_unset: {}) do |value|
35
- decoded_json = EnvParser.parse(value, as: :json)
36
- raise(ArgumentError, 'non-hash value') unless decoded_json.is_a? Hash
86
+ EnvParser.define_type(:hash, if_unset: {}) do |value|
87
+ decoded_json = EnvParser.parse(value, as: :json)
88
+ raise(EnvParser::ValueNotConvertibleError, 'non-hash value') unless decoded_json.is_a? Hash
37
89
 
38
- decoded_json
90
+ decoded_json
91
+ end
92
+ end
39
93
  end