env_parser 0.8.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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