committee 5.5.0 → 5.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/committee/bin/committee_stub.rb +1 -6
  3. data/lib/committee/drivers/open_api_2/driver.rb +21 -33
  4. data/lib/committee/drivers/open_api_2/link.rb +8 -1
  5. data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +1 -2
  6. data/lib/committee/drivers/open_api_2/schema_builder.rb +2 -5
  7. data/lib/committee/drivers.rb +1 -1
  8. data/lib/committee/errors.rb +2 -2
  9. data/lib/committee/middleware/base.rb +2 -2
  10. data/lib/committee/middleware/request_validation.rb +1 -1
  11. data/lib/committee/middleware/stub.rb +1 -1
  12. data/lib/committee/request_unpacker.rb +3 -4
  13. data/lib/committee/schema_validator/hyper_schema/parameter_coercer.rb +41 -41
  14. data/lib/committee/schema_validator/hyper_schema/request_validator.rb +1 -2
  15. data/lib/committee/schema_validator/hyper_schema/response_validator.rb +15 -7
  16. data/lib/committee/schema_validator/hyper_schema/string_params_coercer.rb +60 -60
  17. data/lib/committee/schema_validator/hyper_schema.rb +64 -59
  18. data/lib/committee/schema_validator/open_api_3/request_validator.rb +1 -1
  19. data/lib/committee/schema_validator/open_api_3.rb +10 -5
  20. data/lib/committee/schema_validator/option.rb +1 -6
  21. data/lib/committee/test/schema_coverage.rb +1 -7
  22. data/lib/committee/utils.rb +20 -20
  23. data/lib/committee/version.rb +1 -1
  24. data/test/bin/committee_stub_test.rb +1 -5
  25. data/test/committee_test.rb +0 -1
  26. data/test/drivers/hyper_schema/driver_test.rb +0 -1
  27. data/test/drivers/open_api_2/driver_test.rb +1 -3
  28. data/test/drivers/open_api_2/header_schema_builder_test.rb +1 -9
  29. data/test/drivers/open_api_2/link_test.rb +1 -2
  30. data/test/drivers/open_api_2/parameter_schema_builder_test.rb +6 -45
  31. data/test/drivers/open_api_3/driver_test.rb +5 -5
  32. data/test/drivers_test.rb +19 -28
  33. data/test/middleware/base_test.rb +13 -36
  34. data/test/middleware/request_validation_open_api_3_test.rb +24 -47
  35. data/test/middleware/request_validation_test.rb +19 -53
  36. data/test/middleware/response_validation_open_api_3_test.rb +33 -25
  37. data/test/middleware/response_validation_test.rb +24 -15
  38. data/test/middleware/stub_test.rb +5 -12
  39. data/test/request_unpacker_test.rb +19 -66
  40. data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +3 -3
  41. data/test/schema_validator/hyper_schema/request_validator_test.rb +7 -17
  42. data/test/schema_validator/hyper_schema/response_generator_test.rb +24 -18
  43. data/test/schema_validator/hyper_schema/response_validator_test.rb +3 -7
  44. data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +2 -2
  45. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +16 -17
  46. data/test/schema_validator/open_api_3/request_validator_test.rb +8 -19
  47. data/test/schema_validator/open_api_3/response_validator_test.rb +2 -4
  48. data/test/test/methods_new_version_test.rb +2 -2
  49. data/test/test/methods_test.rb +5 -5
  50. data/test/test/schema_coverage_test.rb +4 -17
  51. data/test/test_helper.rb +6 -13
  52. data/test/validation_error_test.rb +1 -5
  53. metadata +3 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 426a690ac272e53e30d9572a33564ea8cb7f2e92617e9dcd11b8061e32936b2f
4
- data.tar.gz: c335a7d5bb6fe299d6584bf5838ac7972f9be312f431d15db8942cdd3c473cf4
3
+ metadata.gz: c148e784d74f46205ffc12284b2caabbe9e61104e7ab608a57844b50db5af425
4
+ data.tar.gz: 9660dc2a5d8f31425e257854fbeb115dacd3f1ba5d205ea1c7e6555c5a9d5c68
5
5
  SHA512:
6
- metadata.gz: 2e83410d227c6704e208c0bbac5e452a34887921fee1b3f9dbe5c082bbc5861533e49882428e94bb78140d647550047f57b990e7896583a6f18d8ee76d6fdb17
7
- data.tar.gz: 610c2002488ee37be624df996fbfbfb9609c416a911583ed3177a0917061908c0efa71324d56b7b90e77ea538b8f6e00c8785c210bd2d8e67c8398177e3269fd
6
+ metadata.gz: 02e769c6ab664d13e651ac5577bc018615164f0cc047699c3f3245afd99f7cec5667606b613c9abdbc48eb7c8b012daf82279e07adb1dd642ef7920b452d73b4
7
+ data.tar.gz: 9d9fb9fa77dae324e02890837b569395f94312dd70e815ce9d556e9d6075d58849fa7fef0785ccf4999e7fcb8022ce3cfff85fd3c689ca73e83591cf56b197c6
@@ -30,12 +30,7 @@ module Committee
30
30
 
31
31
  # Gets an option parser for command line arguments.
32
32
  def get_options_parser
33
- options = {
34
- driver: nil,
35
- help: false,
36
- port: 9292,
37
- tolerant: false,
38
- }
33
+ options = { driver: nil, help: false, port: 9292, tolerant: false, }
39
34
 
40
35
  parser = OptionParser.new do |opts|
41
36
  opts.banner = "Usage: rackup [options] [JSON Schema file]"
@@ -81,28 +81,21 @@ module Committee
81
81
 
82
82
  # These are fields that the OpenAPI 2 spec considers mandatory to be
83
83
  # included in the document's top level.
84
- REQUIRED_FIELDS = [
85
- :consumes,
86
- :definitions,
87
- :paths,
88
- :produces,
89
- :swagger,
90
- ].map(&:to_s).freeze
84
+ REQUIRED_FIELDS = [:consumes, :definitions, :paths, :produces, :swagger,].map(&:to_s).freeze
91
85
 
92
86
  def find_best_fit_response(link_data)
93
87
  if response_data = link_data["responses"]["200"] || response_data = link_data["responses"][200]
94
- [200, response_data]
88
+ 200
95
89
  elsif response_data = link_data["responses"]["201"] || response_data = link_data["responses"][201]
96
- [201, response_data]
90
+ 201
97
91
  else
98
92
  # Sort responses so that we can try to prefer any 3-digit status code.
99
93
  # If there are none, we'll just take anything from the list.
100
- ordered_responses = link_data["responses"].
101
- select { |k, v| k.to_s =~ /[0-9]{3}/ }
94
+ ordered_responses = link_data["responses"].select { |k, v| k.to_s =~ /[0-9]{3}/ }
102
95
  if first = ordered_responses.first
103
- [first[0].to_i, first[1]]
96
+ first[0].to_i
104
97
  else
105
- [nil, nil]
98
+ nil
106
99
  end
107
100
  end
108
101
  end
@@ -117,9 +110,7 @@ module Committee
117
110
  # that all references to it will still have correct paths (i.e. we can
118
111
  # still find a resource at '#/definitions/resource' instead of
119
112
  # '#/resource').
120
- schema = JsonSchema.parse!({
121
- "definitions" => data['definitions'],
122
- })
113
+ schema = JsonSchema.parse!({ "definitions" => data['definitions'], })
123
114
  schema.expand_references!
124
115
  schema.uri = DEFINITIONS_PSEUDO_URI
125
116
 
@@ -174,19 +165,16 @@ module Committee
174
165
  schemas_data["properties"][href]["properties"][method] = schema_data
175
166
  end
176
167
 
177
- # Arbitrarily pick one response for the time being. Prefers in order:
178
- # a 200, 201, any 3-digit numerical response, then anything at all.
179
- status, response_data = find_best_fit_response(link_data)
180
- if status
181
- link.status_success = status
182
-
183
- # A link need not necessarily specify a target schema.
184
- if response_data["schema"]
185
- target_schemas_data["properties"][href]["properties"][method] =
186
- response_data["schema"]
187
- end
168
+ target_schemas_data["properties"][href]["properties"][method] ||= { "properties" => {} }
169
+ link_data["responses"].each do |key, response_data|
170
+ status = key.to_i
171
+ next unless response_data["schema"]
172
+
173
+ target_schemas_data["properties"][href]["properties"][method]["properties"][status] = response_data["schema"]
188
174
  end
189
175
 
176
+ link.status_success = find_best_fit_response(link_data)
177
+
190
178
  rx = %r{^#{href_to_regex(link.href)}$}
191
179
  Committee.log_debug "Created route: #{link.method} #{link.href} (regex #{rx})"
192
180
 
@@ -199,10 +187,8 @@ module Committee
199
187
  # #parse_definitions!, but what we're doing here is prefixing references
200
188
  # with a specialized internal URI so that they can reference definitions
201
189
  # from another document in the store.
202
- schemas =
203
- rewrite_references_and_parse(schemas_data, store)
204
- target_schemas =
205
- rewrite_references_and_parse(target_schemas_data, store)
190
+ schemas = rewrite_references_and_parse(schemas_data, store)
191
+ target_schemas = rewrite_references_and_parse(target_schemas_data, store)
206
192
 
207
193
  # As noted above, now that we've parsed our aggregate response schema, go
208
194
  # back through each link and them their response schema.
@@ -218,8 +204,10 @@ module Committee
218
204
  end
219
205
 
220
206
  # response
221
- link.target_schema =
222
- target_schemas.properties[link.href].properties[method]
207
+ link.target_schemas = {}
208
+ target_schemas.properties[link.href].properties[method].properties.each do |status, schema|
209
+ link.target_schemas[status] = schema
210
+ end
223
211
  end
224
212
  end
225
213
 
@@ -23,13 +23,20 @@ module Committee
23
23
 
24
24
  # The link's output schema. i.e. How we validate an endpoint's response
25
25
  # data.
26
- attr_accessor :target_schema
26
+ attr_accessor :target_schemas
27
27
 
28
28
  attr_accessor :header_schema
29
29
 
30
30
  def rel
31
31
  raise "Committee: rel not implemented for OpenAPI"
32
32
  end
33
+
34
+ def target_schema
35
+ target_schemas[status_success] ||
36
+ target_schemas[200] ||
37
+ target_schemas[201] ||
38
+ target_schemas.values.first
39
+ end
33
40
  end
34
41
  end
35
42
  end
@@ -17,8 +17,7 @@ module Committee
17
17
  check_required_fields!(body_param)
18
18
 
19
19
  if link_data["parameters"].detect { |p| p["in"] == "form" } != nil
20
- raise ArgumentError, "Committee: can't mix body parameter " \
21
- "with form parameters."
20
+ raise ArgumentError, "Committee: can't mix body parameter with form parameters."
22
21
  end
23
22
 
24
23
  schema_data = body_param["schema"]
@@ -10,17 +10,14 @@ module Committee
10
10
 
11
11
  private
12
12
 
13
- LINK_REQUIRED_FIELDS = [
14
- :name
15
- ].map(&:to_s).freeze
13
+ LINK_REQUIRED_FIELDS = [:name].map(&:to_s).freeze
16
14
 
17
15
  attr_accessor :link_data
18
16
 
19
17
  def check_required_fields!(param_data)
20
18
  LINK_REQUIRED_FIELDS.each do |field|
21
19
  if !param_data[field]
22
- raise ArgumentError,
23
- "Committee: no #{field} section in link data."
20
+ raise ArgumentError, "Committee: no #{field} section in link data."
24
21
  end
25
22
  end
26
23
  end
@@ -65,7 +65,7 @@ module Committee
65
65
  'from next version. Pass config `strict_reference_validation: true` (or false, if you must) ' +
66
66
  'to quiet this warning.')
67
67
  opts[:strict_reference_validation] ||= false
68
-
68
+
69
69
  openapi = OpenAPIParser.parse_with_filepath(hash, schema_path, opts)
70
70
  return Committee::Drivers::OpenAPI3::Driver.new.parse(openapi)
71
71
  end
@@ -10,7 +10,7 @@ module Committee
10
10
  class InvalidRequest < Error
11
11
  attr_reader :original_error
12
12
 
13
- def initialize(error_message=nil, original_error: nil)
13
+ def initialize(error_message = nil, original_error: nil)
14
14
  @original_error = original_error
15
15
  super(error_message)
16
16
  end
@@ -19,7 +19,7 @@ module Committee
19
19
  class InvalidResponse < Error
20
20
  attr_reader :original_error
21
21
 
22
- def initialize(error_message=nil, original_error: nil)
22
+ def initialize(error_message = nil, original_error: nil)
23
23
  @original_error = original_error
24
24
  super(error_message)
25
25
  end
@@ -3,7 +3,7 @@
3
3
  module Committee
4
4
  module Middleware
5
5
  class Base
6
- def initialize(app, options={})
6
+ def initialize(app, options = {})
7
7
  @app = app
8
8
 
9
9
  @error_class = options.fetch(:error_class, Committee::ValidationError)
@@ -14,7 +14,7 @@ module Committee
14
14
  @schema = self.class.get_schema(options)
15
15
 
16
16
  @router = @schema.build_router(options)
17
- @accept_request_filter = options[:accept_request_filter] || -> (_) { true }
17
+ @accept_request_filter = options[:accept_request_filter] || ->(_) { true }
18
18
  end
19
19
 
20
20
  def call(env)
@@ -3,7 +3,7 @@
3
3
  module Committee
4
4
  module Middleware
5
5
  class RequestValidation < Base
6
- def initialize(app, options={})
6
+ def initialize(app, options = {})
7
7
  super
8
8
 
9
9
  @strict = options[:strict]
@@ -5,7 +5,7 @@
5
5
  module Committee
6
6
  module Middleware
7
7
  class Stub < Base
8
- def initialize(app, options={})
8
+ def initialize(app, options = {})
9
9
  super
10
10
 
11
11
  # A bug in Committee's cache implementation meant that it wasn't working
@@ -20,7 +20,7 @@ module Committee
20
20
  end
21
21
  end
22
22
 
23
- def initialize(options={})
23
+ def initialize(options = {})
24
24
  @allow_form_params = options[:allow_form_params]
25
25
  @allow_get_body = options[:allow_get_body]
26
26
  @allow_query_params = options[:allow_query_params]
@@ -32,7 +32,7 @@ module Committee
32
32
  # if Content-Type is empty or JSON, and there was a request body, try to
33
33
  # interpret it as JSON
34
34
  params = if !request.media_type || request.media_type =~ %r{application/(?:.*\+)?json}
35
- parse_json(request)
35
+ parse_json(request)
36
36
  elsif @optimistic_json
37
37
  begin
38
38
  parse_json(request)
@@ -87,8 +87,7 @@ module Committee
87
87
  # We want a hash specifically. '42', 42, and [42] will all be
88
88
  # decoded properly, but we can't use them here.
89
89
  if !hash.is_a?(Hash)
90
- raise BadRequest,
91
- "Invalid JSON input. Require object with parameters as keys."
90
+ raise BadRequest, "Invalid JSON input. Require object with parameters as keys."
92
91
  end
93
92
  self.class.indifferent_params(hash)
94
93
  end
@@ -18,61 +18,61 @@ module Committee
18
18
 
19
19
  private
20
20
 
21
- def coerce_object!(hash, schema)
22
- return false unless schema.respond_to?(:properties)
21
+ def coerce_object!(hash, schema)
22
+ return false unless schema.respond_to?(:properties)
23
23
 
24
- is_coerced = false
25
- schema.properties.each do |k, s|
26
- original_val = hash[k]
27
- unless original_val.nil?
28
- new_value, is_changed = coerce_value!(original_val, s)
29
- if is_changed
30
- hash[k] = new_value
31
- is_coerced = true
32
- end
24
+ is_coerced = false
25
+ schema.properties.each do |k, s|
26
+ original_val = hash[k]
27
+ unless original_val.nil?
28
+ new_value, is_changed = coerce_value!(original_val, s)
29
+ if is_changed
30
+ hash[k] = new_value
31
+ is_coerced = true
33
32
  end
34
33
  end
35
-
36
- is_coerced
37
34
  end
38
35
 
39
- def coerce_value!(original_val, s)
40
- s.type.each do |to_type|
41
- if @coerce_date_times && to_type == "string" && s.format == "date-time"
42
- coerced_val = parse_date_time(original_val)
43
- return coerced_val, true if coerced_val
44
- end
45
-
46
- return original_val, true if @coerce_recursive && (to_type == "array") && coerce_array_data!(original_val, s)
36
+ is_coerced
37
+ end
47
38
 
48
- return original_val, true if @coerce_recursive && (to_type == "object") && coerce_object!(original_val, s)
39
+ def coerce_value!(original_val, s)
40
+ s.type.each do |to_type|
41
+ if @coerce_date_times && to_type == "string" && s.format == "date-time"
42
+ coerced_val = parse_date_time(original_val)
43
+ return coerced_val, true if coerced_val
49
44
  end
50
- return nil, false
45
+
46
+ return original_val, true if @coerce_recursive && (to_type == "array") && coerce_array_data!(original_val, s)
47
+
48
+ return original_val, true if @coerce_recursive && (to_type == "object") && coerce_object!(original_val, s)
51
49
  end
50
+ return nil, false
51
+ end
52
52
 
53
- def coerce_array_data!(original_val, schema)
54
- return false unless schema.respond_to?(:items)
55
- return false unless original_val.is_a?(Array)
53
+ def coerce_array_data!(original_val, schema)
54
+ return false unless schema.respond_to?(:items)
55
+ return false unless original_val.is_a?(Array)
56
56
 
57
- is_coerced = false
58
- original_val.each_with_index do |d, index|
59
- new_value, is_changed = coerce_value!(d, schema.items)
60
- if is_changed
61
- original_val[index] = new_value
62
- is_coerced = true
63
- end
57
+ is_coerced = false
58
+ original_val.each_with_index do |d, index|
59
+ new_value, is_changed = coerce_value!(d, schema.items)
60
+ if is_changed
61
+ original_val[index] = new_value
62
+ is_coerced = true
64
63
  end
65
-
66
- is_coerced
67
64
  end
68
65
 
69
- def parse_date_time(original_val)
70
- begin
71
- DateTime.parse(original_val)
72
- rescue ArgumentError => e
73
- raise ::Committee::InvalidResponse unless e.message =~ /invalid date/
74
- end
66
+ is_coerced
67
+ end
68
+
69
+ def parse_date_time(original_val)
70
+ begin
71
+ DateTime.parse(original_val)
72
+ rescue ArgumentError => e
73
+ raise ::Committee::InvalidResponse unless e.message =~ /invalid date/
75
74
  end
75
+ end
76
76
  end
77
77
  end
78
78
  end
@@ -35,8 +35,7 @@ module Committee
35
35
  content_type = ::Committee::SchemaValidator.request_media_type(request)
36
36
  if content_type && @link.enc_type && !empty_request?(request)
37
37
  unless Rack::Mime.match?(content_type, @link.enc_type)
38
- raise Committee::InvalidRequest,
39
- %{"Content-Type" request header must be set to "#{@link.enc_type}".}
38
+ raise Committee::InvalidRequest, %{"Content-Type" request header must be set to "#{@link.enc_type}".}
40
39
  end
41
40
  end
42
41
  end
@@ -11,7 +11,14 @@ module Committee
11
11
  @validate_success_only = options[:validate_success_only]
12
12
  @allow_blank_structures = options[:allow_blank_structures]
13
13
 
14
- @validator = JsonSchema::Validator.new(target_schema(link))
14
+ @validators = {}
15
+ if link.is_a? Drivers::OpenAPI2::Link
16
+ link.target_schemas.each do |status, schema|
17
+ @validators[status] = JsonSchema::Validator.new(target_schema(link))
18
+ end
19
+ else
20
+ @validators[link.status_success] = JsonSchema::Validator.new(target_schema(link))
21
+ end
15
22
  end
16
23
 
17
24
  def call(status, headers, data)
@@ -45,9 +52,12 @@ module Committee
45
52
  end
46
53
 
47
54
  begin
48
- if Committee::Middleware::ResponseValidation.validate?(status, validate_success_only) && !@validator.validate(data)
49
- errors = JsonSchema::SchemaError.aggregate(@validator.errors).join("\n")
50
- raise InvalidResponse, "Invalid response.\n\n#{errors}"
55
+ if Committee::Middleware::ResponseValidation.validate?(status, validate_success_only)
56
+ raise InvalidResponse, "Invalid response.#{@link.href} status code #{status} definition does not exist" if @validators[status].nil?
57
+ if !@validators[status].validate(data)
58
+ errors = JsonSchema::SchemaError.aggregate(@validators[status].errors).join("\n")
59
+ raise InvalidResponse, "Invalid response.\n\n#{errors}"
60
+ end
51
61
  end
52
62
  rescue => e
53
63
  raise InvalidResponse, "Invalid response.\n\nschema is undefined" if /undefined method .all_of. for nil/ =~ e.message
@@ -66,12 +76,10 @@ module Committee
66
76
  end
67
77
  end
68
78
 
69
-
70
79
  def check_content_type!(response)
71
80
  if @link.media_type
72
81
  unless Rack::Mime.match?(response_media_type(response), @link.media_type)
73
- raise Committee::InvalidResponse,
74
- %{"Content-Type" response header must be set to "#{@link.media_type}".}
82
+ raise Committee::InvalidResponse, %{"Content-Type" response header must be set to "#{@link.media_type}".}
75
83
  end
76
84
  end
77
85
  end
@@ -27,78 +27,78 @@ module Committee
27
27
 
28
28
  private
29
29
 
30
- def coerce_object!(hash, schema)
31
- return false unless schema.respond_to?(:properties)
30
+ def coerce_object!(hash, schema)
31
+ return false unless schema.respond_to?(:properties)
32
32
 
33
- is_coerced = false
34
- schema.properties.each do |k, s|
35
- original_val = hash[k]
36
- unless original_val.nil?
37
- new_value, is_changed = coerce_value!(original_val, s)
38
- if is_changed
39
- hash[k] = new_value
40
- is_coerced = true
41
- end
33
+ is_coerced = false
34
+ schema.properties.each do |k, s|
35
+ original_val = hash[k]
36
+ unless original_val.nil?
37
+ new_value, is_changed = coerce_value!(original_val, s)
38
+ if is_changed
39
+ hash[k] = new_value
40
+ is_coerced = true
42
41
  end
43
42
  end
44
-
45
- is_coerced
46
43
  end
47
44
 
48
- def coerce_value!(original_val, s)
49
- unless original_val.nil?
50
- s.type.each do |to_type|
51
- case to_type
52
- when "null"
53
- return nil, true if original_val.empty?
54
- when "integer"
55
- begin
56
- return Integer(original_val), true
57
- rescue ArgumentError => e
58
- raise e unless e.message =~ /invalid value for Integer/
59
- end
60
- when "number"
61
- begin
62
- return Float(original_val), true
63
- rescue ArgumentError => e
64
- raise e unless e.message =~ /invalid value for Float/
65
- end
66
- when "boolean"
67
- if original_val == "true" || original_val == "1"
68
- return true, true
69
- end
70
- if original_val == "false" || original_val == "0"
71
- return false, true
72
- end
73
- when "array"
74
- if @coerce_recursive && coerce_array_data!(original_val, s)
75
- return original_val, true # change original value
76
- end
77
- when "object"
78
- if @coerce_recursive && coerce_object!(original_val, s)
79
- return original_val, true # change original value
80
- end
81
- end
45
+ is_coerced
46
+ end
47
+
48
+ def coerce_value!(original_val, s)
49
+ unless original_val.nil?
50
+ s.type.each do |to_type|
51
+ case to_type
52
+ when "null"
53
+ return nil, true if original_val.empty?
54
+ when "integer"
55
+ begin
56
+ return Integer(original_val), true
57
+ rescue ArgumentError => e
58
+ raise e unless e.message =~ /invalid value for Integer/
59
+ end
60
+ when "number"
61
+ begin
62
+ return Float(original_val), true
63
+ rescue ArgumentError => e
64
+ raise e unless e.message =~ /invalid value for Float/
65
+ end
66
+ when "boolean"
67
+ if original_val == "true" || original_val == "1"
68
+ return true, true
69
+ end
70
+ if original_val == "false" || original_val == "0"
71
+ return false, true
72
+ end
73
+ when "array"
74
+ if @coerce_recursive && coerce_array_data!(original_val, s)
75
+ return original_val, true # change original value
76
+ end
77
+ when "object"
78
+ if @coerce_recursive && coerce_object!(original_val, s)
79
+ return original_val, true # change original value
80
+ end
82
81
  end
83
82
  end
84
- return nil, false
85
83
  end
84
+ return nil, false
85
+ end
86
86
 
87
- def coerce_array_data!(original_val, schema)
88
- return false unless schema.respond_to?(:items)
89
- return false unless original_val.is_a?(Array)
87
+ def coerce_array_data!(original_val, schema)
88
+ return false unless schema.respond_to?(:items)
89
+ return false unless original_val.is_a?(Array)
90
90
 
91
- is_coerced = false
92
- original_val.each_with_index do |d, index|
93
- new_value, is_changed = coerce_value!(d, schema.items)
94
- if is_changed
95
- original_val[index] = new_value
96
- is_coerced = true
97
- end
91
+ is_coerced = false
92
+ original_val.each_with_index do |d, index|
93
+ new_value, is_changed = coerce_value!(d, schema.items)
94
+ if is_changed
95
+ original_val[index] = new_value
96
+ is_coerced = true
98
97
  end
99
-
100
- is_coerced
101
98
  end
99
+
100
+ is_coerced
101
+ end
102
102
  end
103
103
  end
104
104
  end