committee 2.0.0.pre8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a52179d89e7de15a76b440454d27fc478ca2e75b
4
- data.tar.gz: 5a98b675cffcefd898612e6806dc466d58fa9d64
3
+ metadata.gz: 0719ce2f2d3336816d822c41eace6161265ab86b
4
+ data.tar.gz: 8eaf8c70a09ed4ef5b6613897e54d370f8523ea6
5
5
  SHA512:
6
- metadata.gz: 59cab2ff0859d8ae77a734f3bdfe5103c9b52c70c2cbca18846739e9afff0280a900910479c72697e743bfc92b833864ce34529fd33a8ff45dec84bb03d6d2a0
7
- data.tar.gz: 4034113794bb7f991542919a7f8f0b22bb8b4c5c52a1c9e5be03dba15ece0a3cb8d0fcaa451cd716e6c935d28f6d3185d200b06f0e3640e653c5d62179b09f5d
6
+ metadata.gz: c94926b7b0f4a0e92b99d448d5eb186c751b5b29fe7734038027f824ae2d892e8d93939d9c0d6f738b11d21926ef4235ac8a0818b2a03d8b4f421cbab5d396cf
7
+ data.tar.gz: 5df57d46e4d3f639705339a88c0464eb9c1677d314eccf1ea877d8449b13fb9f8d3da3d56f865fe1da5fcfe038eb1d3b2c43754de064a825a05ff4062447e5d6
@@ -9,6 +9,7 @@ module Committee::Middleware
9
9
  @optimistic_json = options.fetch(:optimistic_json, false)
10
10
  @strict = options[:strict]
11
11
  @coerce_date_times = options.fetch(:coerce_date_times, false)
12
+ @coerce_recursive = options.fetch(:coerce_recursive, true)
12
13
 
13
14
  @coerce_form_params = options.fetch(:coerce_form_params,
14
15
  @schema.driver.default_coerce_form_params)
@@ -23,29 +24,18 @@ module Committee::Middleware
23
24
 
24
25
  def handle(request)
25
26
  link, param_matches = @router.find_request_link(request)
26
- path_params = {}
27
27
 
28
28
  if link
29
29
  # Attempts to coerce parameters that appear in a link's URL to Ruby
30
30
  # types that can be validated with a schema.
31
31
  if @coerce_path_params
32
- path_params = param_matches.merge(
33
- Committee::StringParamsCoercer.new(
34
- param_matches,
35
- link.schema
36
- ).call
37
- )
32
+ Committee::StringParamsCoercer.new(param_matches, link.schema, coerce_recursive: @coerce_recursive).call!
38
33
  end
39
34
 
40
35
  # Attempts to coerce parameters that appear in a query string to Ruby
41
36
  # types that can be validated with a schema.
42
37
  if @coerce_query_params && !request.GET.nil? && !link.schema.nil?
43
- request.env["rack.request.query_hash"].merge!(
44
- Committee::StringParamsCoercer.new(
45
- request.GET,
46
- link.schema
47
- ).call
48
- )
38
+ Committee::StringParamsCoercer.new(request.GET, link.schema, coerce_recursive: @coerce_recursive).call!
49
39
  end
50
40
  end
51
41
 
@@ -58,14 +48,14 @@ module Committee::Middleware
58
48
  schema: link ? link.schema : nil
59
49
  ).call
60
50
 
61
- request.env[@params_key].merge!(path_params)
51
+ request.env[@params_key].merge!(param_matches) if param_matches
62
52
 
63
53
  if link
64
54
  validator = Committee::RequestValidator.new(link, check_content_type: @check_content_type)
65
55
  validator.call(request, request.env[@params_key])
66
56
 
67
- parameter_coerce(request, link, @params_key)
68
- parameter_coerce(request, link, "rack.request.query_hash") if !request.GET.nil? && !link.schema.nil?
57
+ parameter_coerce!(request, link, @params_key)
58
+ parameter_coerce!(request, link, "rack.request.query_hash") if !request.GET.nil? && !link.schema.nil?
69
59
 
70
60
  @app.call(request.env)
71
61
  elsif @strict
@@ -90,13 +80,10 @@ module Committee::Middleware
90
80
 
91
81
  private
92
82
 
93
- def parameter_coerce(request, link, coerce_key)
94
- request.env[coerce_key].merge!(
95
- Committee::ParameterCoercer
96
- .new(request.env[coerce_key], link.schema,
97
- coerce_date_times: @coerce_date_times)
98
- .call
99
- )
83
+ def parameter_coerce!(request, link, coerce_key)
84
+ Committee::ParameterCoercer.
85
+ new(request.env[coerce_key], link.schema, coerce_date_times: @coerce_date_times, coerce_recursive: @coerce_recursive).
86
+ call!
100
87
  end
101
88
  end
102
89
  end
@@ -5,31 +5,63 @@ module Committee
5
5
  @schema = schema
6
6
 
7
7
  @coerce_date_times = options.fetch(:coerce_date_times, false)
8
+ @coerce_recursive = options.fetch(:coerce_recursive, false)
8
9
  end
9
10
 
10
- def call
11
- coerced = {}
12
- return coerced unless @schema.respond_to?(:properties)
11
+ def call!
12
+ coerce_object!(@params, @schema)
13
+ end
14
+
15
+ private
13
16
 
14
- @schema.properties.each do |k, s|
15
- original_val = @params[k]
17
+ def coerce_object!(hash, schema)
18
+ return false unless schema.respond_to?(:properties)
16
19
 
17
- unless original_val.nil?
18
- s.type.each do |to_type|
19
- if @coerce_date_times && to_type == "string" && s.format == "date-time"
20
- coerce_val = parse_date_time(original_val)
21
- coerced[k] = coerce_val if coerce_val
20
+ is_coerced = false
21
+ schema.properties.each do |k, s|
22
+ original_val = hash[k]
23
+ unless original_val.nil?
24
+ new_value, is_changed = coerce_value!(original_val, s)
25
+ if is_changed
26
+ hash[k] = new_value
27
+ is_coerced = true
22
28
  end
29
+ end
30
+ end
31
+
32
+ is_coerced
33
+ end
23
34
 
24
- break if coerced.key?(k)
35
+ def coerce_value!(original_val, s)
36
+ s.type.each do |to_type|
37
+ if @coerce_date_times && to_type == "string" && s.format == "date-time"
38
+ coerced_val = parse_date_time(original_val)
39
+ return coerced_val, true if coerced_val
25
40
  end
41
+
42
+ return original_val, true if @coerce_recursive && (to_type == "array") && coerce_array_data!(original_val, s)
43
+
44
+ return original_val, true if @coerce_recursive && (to_type == "object") && coerce_object!(original_val, s)
26
45
  end
46
+ return nil, false
27
47
  end
28
48
 
29
- coerced
30
- end
49
+ def coerce_array_data!(original_val, schema)
50
+ return false unless schema.respond_to?(:items)
51
+ return false unless original_val.is_a?(Array)
52
+
53
+ is_coerced = false
54
+ original_val.each_with_index do |d, index|
55
+ new_value, is_changed = coerce_value!(d, schema.items)
56
+ if is_changed
57
+ original_val[index] = new_value
58
+ is_coerced = true
59
+ end
60
+ end
61
+
62
+ is_coerced
63
+ end
31
64
 
32
- private
33
65
  def parse_date_time(original_val)
34
66
  begin
35
67
  DateTime.parse(original_val)
@@ -31,10 +31,7 @@ module Committee
31
31
  p = @request.POST
32
32
 
33
33
  if @coerce_form_params && @schema
34
- p.merge!(Committee::StringParamsCoercer.new(
35
- p,
36
- @schema
37
- ).call)
34
+ Committee::StringParamsCoercer.new(p, @schema).call!
38
35
  end
39
36
 
40
37
  p
@@ -10,41 +10,90 @@ module Committee
10
10
  # errors are simply ignored and expected to be handled later by schema
11
11
  # validation.
12
12
  class StringParamsCoercer
13
- def initialize(query_hash, schema)
13
+ def initialize(query_hash, schema, options = {})
14
14
  @query_hash = query_hash
15
15
  @schema = schema
16
+
17
+ @coerce_recursive = options.fetch(:coerce_recursive, false)
18
+ end
19
+
20
+ def call!
21
+ coerce_object!(@query_hash, @schema)
16
22
  end
17
23
 
18
- def call
19
- coerced = {}
20
- @schema.properties.each do |k, s|
21
- original_val = @query_hash[k]
24
+ private
25
+
26
+ def coerce_object!(hash, schema)
27
+ return false unless schema.respond_to?(:properties)
28
+
29
+ is_coerced = false
30
+ schema.properties.each do |k, s|
31
+ original_val = hash[k]
32
+ unless original_val.nil?
33
+ new_value, is_changed = coerce_value!(original_val, s)
34
+ if is_changed
35
+ hash[k] = new_value
36
+ is_coerced = true
37
+ end
38
+ end
39
+ end
40
+
41
+ is_coerced
42
+ end
43
+
44
+ def coerce_value!(original_val, s)
22
45
  unless original_val.nil?
23
46
  s.type.each do |to_type|
24
47
  case to_type
25
- when "null"
26
- coerced[k] = nil if original_val.empty?
27
- when "integer"
28
- begin
29
- coerced[k] = Integer(original_val)
30
- rescue ArgumentError => e
31
- raise e unless e.message =~ /invalid value for Integer/
32
- end
33
- when "number"
34
- begin
35
- coerced[k] = Float(original_val)
36
- rescue ArgumentError => e
37
- raise e unless e.message =~ /invalid value for Float/
38
- end
39
- when "boolean"
40
- coerced[k] = true if original_val == "true" || original_val == "1"
41
- coerced[k] = false if original_val == "false" || original_val == "0"
48
+ when "null"
49
+ return nil, true if original_val.empty?
50
+ when "integer"
51
+ begin
52
+ return Integer(original_val), true
53
+ rescue ArgumentError => e
54
+ raise e unless e.message =~ /invalid value for Integer/
55
+ end
56
+ when "number"
57
+ begin
58
+ return Float(original_val), true
59
+ rescue ArgumentError => e
60
+ raise e unless e.message =~ /invalid value for Float/
61
+ end
62
+ when "boolean"
63
+ if original_val == "true" || original_val == "1"
64
+ return true, true
65
+ end
66
+ if original_val == "false" || original_val == "0"
67
+ return false, true
68
+ end
69
+ when "array"
70
+ if @coerce_recursive && coerce_array_data!(original_val, s)
71
+ return original_val, true # change original value
72
+ end
73
+ when "object"
74
+ if @coerce_recursive && coerce_object!(original_val, s)
75
+ return original_val, true # change original value
76
+ end
42
77
  end
43
- break if coerced.key?(k)
44
78
  end
45
79
  end
80
+ return nil, false
81
+ end
82
+
83
+ def coerce_array_data!(original_val, schema)
84
+ return false unless schema.respond_to?(:items)
85
+ return false unless original_val.is_a?(Array)
86
+
87
+ is_coerced = false
88
+ original_val.each_with_index do |d, index|
89
+ new_value, is_changed = coerce_value!(d, schema.items)
90
+ if is_changed
91
+ original_val[index] = new_value
92
+ is_coerced = true
93
+ end
94
+ end
95
+
96
+ is_coerced
46
97
  end
47
- coerced
48
- end
49
98
  end
50
99
  end
@@ -7,6 +7,50 @@ describe Committee::Middleware::RequestValidation do
7
7
  @app
8
8
  end
9
9
 
10
+ ARRAY_PROPERTY = [
11
+ {
12
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
13
+ "per_page" => 1,
14
+ "nested_coercer_object" => {
15
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
16
+ "threshold" => 1.5
17
+ },
18
+ "nested_no_coercer_object" => {
19
+ "per_page" => 1,
20
+ "threshold" => 1.5
21
+ },
22
+ "nested_coercer_array" => [
23
+ {
24
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
25
+ "threshold" => 1.5
26
+ }
27
+ ],
28
+ "nested_no_coercer_array" => [
29
+ {
30
+ "per_page" => 1,
31
+ "threshold" => 1.5
32
+ }
33
+ ],
34
+ "integer_array" => [
35
+ 1, 2, 3
36
+ ],
37
+ "datetime_array" => [
38
+ "2016-04-01T16:00:00.000+09:00",
39
+ "2016-04-01T17:00:00.000+09:00",
40
+ "2016-04-01T18:00:00.000+09:00"
41
+ ]
42
+ },
43
+ {
44
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
45
+ "per_page" => 1,
46
+ "threshold" => 1.5
47
+ },
48
+ {
49
+ "threshold" => 1.5,
50
+ "per_page" => 1
51
+ }
52
+ ]
53
+
10
54
  it "passes through a valid request" do
11
55
  @app = new_rack_app(schema: hyper_schema)
12
56
  params = {
@@ -35,18 +79,162 @@ describe Committee::Middleware::RequestValidation do
35
79
  assert_equal 200, last_response.status
36
80
  end
37
81
 
38
- it "passes given a datetime and with coerce_date_times enabled on POST endpoint" do
82
+ it "passes a nested object with recursive option" do
39
83
  key_name = "update_time"
40
84
  params = {
41
- key_name => "2016-04-01T16:00:00.000+09:00"
85
+ key_name => "2016-04-01T16:00:00.000+09:00",
86
+ "query" => "cloudnasium",
87
+ "array_property" => ARRAY_PROPERTY
42
88
  }
43
89
 
44
90
  check_parameter = lambda { |env|
91
+ hash = env['rack.request.query_hash']
92
+ assert_equal DateTime, hash['array_property'].first['update_time'].class
93
+ assert_equal 1, hash['array_property'].first['per_page']
94
+ assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
95
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
96
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
97
+ assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
98
+ assert_equal DateTime, hash[key_name].class
99
+ [200, {}, []]
100
+ }
101
+
102
+ @app = new_rack_app_with_lambda(check_parameter,
103
+ coerce_query_params: true,
104
+ coerce_recursive: true,
105
+ coerce_date_times: true,
106
+ schema: hyper_schema)
107
+
108
+ get "/search/apps", params
109
+ assert_equal 200, last_response.status
110
+ end
111
+
112
+ it "passes a nested object with coerce_recursive false" do
113
+ key_name = "update_time"
114
+ params = {
115
+ key_name => "2016-04-01T16:00:00.000+09:00",
116
+ "query" => "cloudnasium",
117
+ "array_property" => ARRAY_PROPERTY
118
+ }
119
+
120
+ @app = new_rack_app(coerce_query_params: true, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
121
+
122
+ get "/search/apps", params
123
+ assert_equal 400, last_response.status # schema expect integer but we don't convert string to integer, so 400
124
+ end
125
+
126
+ it "passes a nested object with coerce_recursive default(true)" do
127
+ key_name = "update_time"
128
+ params = {
129
+ key_name => "2016-04-01T16:00:00.000+09:00",
130
+ "query" => "cloudnasium",
131
+ "array_property" => ARRAY_PROPERTY
132
+ }
133
+
134
+ @app = new_rack_app(coerce_query_params: true, coerce_date_times: true, schema: hyper_schema)
135
+
136
+ get "/search/apps", params
137
+ assert_equal 200, last_response.status # schema expect integer but we don't convert string to integer, so 400
138
+ end
139
+
140
+ it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
141
+ key_name = "update_time"
142
+ params = {
143
+ key_name => "2016-04-01T16:00:00.000+09:00",
144
+ "array_property" => ARRAY_PROPERTY
145
+ }
146
+
147
+ check_parameter = lambda { |env|
148
+ hash = env['committee.params']
149
+ assert_equal DateTime, hash['array_property'].first['update_time'].class
150
+ assert_equal 1, hash['array_property'].first['per_page']
151
+ assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
152
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
153
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
154
+ assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
45
155
  assert_equal DateTime, env['committee.params'][key_name].class
46
156
  [200, {}, []]
47
157
  }
48
158
 
49
- @app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, schema: hyper_schema)
159
+ @app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: true, schema: hyper_schema)
160
+
161
+ header "Content-Type", "application/json"
162
+ post "/apps", JSON.generate(params)
163
+ assert_equal 200, last_response.status
164
+ end
165
+
166
+ it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
167
+ key_name = "update_time"
168
+ params = {
169
+ key_name => "2016-04-01T16:00:00.000+09:00",
170
+ "array_property" => ARRAY_PROPERTY
171
+ }
172
+
173
+ check_parameter = lambda { |env|
174
+ hash = env['committee.params']
175
+ assert_equal String, hash['array_property'].first['update_time'].class
176
+ assert_equal 1, hash['array_property'].first['per_page']
177
+ assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
178
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
179
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
180
+ assert_equal String, hash['array_property'].first['datetime_array'][0].class
181
+ assert_equal String, env['committee.params'][key_name].class
182
+ [200, {}, []]
183
+ }
184
+
185
+ @app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
186
+
187
+ header "Content-Type", "application/json"
188
+ post "/apps", JSON.generate(params)
189
+ assert_equal 200, last_response.status
190
+ end
191
+
192
+ it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=true on POST endpoint" do
193
+ key_name = "update_time"
194
+ params = {
195
+ key_name => "2016-04-01T16:00:00.000+09:00",
196
+ "array_property" => ARRAY_PROPERTY
197
+ }
198
+
199
+ check_parameter = lambda { |env|
200
+ hash = env['committee.params']
201
+ assert_equal String, hash['array_property'].first['update_time'].class
202
+ assert_equal 1, hash['array_property'].first['per_page']
203
+ assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
204
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
205
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
206
+ assert_equal String, hash['array_property'].first['datetime_array'][0].class
207
+ assert_equal DateTime, env['committee.params'][key_name].class
208
+ [200, {}, []]
209
+ }
210
+
211
+ @app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
212
+
213
+ header "Content-Type", "application/json"
214
+ post "/apps", JSON.generate(params)
215
+ assert_equal 200, last_response.status
216
+ end
217
+
218
+ it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=false on POST endpoint" do
219
+ key_name = "update_time"
220
+ params = {
221
+ key_name => "2016-04-01T16:00:00.000+09:00",
222
+ "array_property" => ARRAY_PROPERTY
223
+ }
224
+
225
+ check_parameter = lambda { |env|
226
+ hash = env['committee.params']
227
+ assert_equal String, hash['array_property'].first['update_time'].class
228
+ assert_equal 1, hash['array_property'].first['per_page']
229
+ assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
230
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
231
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
232
+ assert_equal String, hash['array_property'].first['datetime_array'][0].class
233
+ assert_equal String, env['committee.params'][key_name].class
234
+ [200, {}, []]
235
+ }
236
+
237
+ @app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
50
238
 
51
239
  header "Content-Type", "application/json"
52
240
  post "/apps", JSON.generate(params)
@@ -153,7 +341,12 @@ describe Committee::Middleware::RequestValidation do
153
341
  end
154
342
 
155
343
  it "passes through a valid request for OpenAPI" do
156
- @app = new_rack_app(schema: open_api_2_schema)
344
+ check_parameter = lambda { |env|
345
+ assert_equal 3, env['rack.request.query_hash']['limit']
346
+ [200, {}, []]
347
+ }
348
+
349
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_2_schema)
157
350
  get "/api/pets?limit=3"
158
351
  assert_equal 200, last_response.status
159
352
  end
@@ -12,22 +12,100 @@ describe Committee::ParameterCoercer do
12
12
 
13
13
  it "pass datetime string" do
14
14
  params = { "update_time" => "2016-04-01T16:00:00.000+09:00"}
15
- converted_params = call(params, coerce_date_times: true)
15
+ call(params, coerce_date_times: true)
16
16
 
17
- assert_kind_of DateTime, converted_params["update_time"]
17
+ assert_kind_of DateTime, params["update_time"]
18
+ end
19
+
20
+ it "don't change object type" do
21
+ params = HashLikeObject.new
22
+ params["update_time"] = "2016-04-01T16:00:00.000+09:00"
23
+ call(params, coerce_date_times: true)
24
+
25
+ assert_kind_of DateTime, params["update_time"]
26
+ assert_kind_of HashLikeObject, params
18
27
  end
19
28
 
20
29
  it "pass invalid datetime string, not convert" do
21
- params = { "update_time" => "llmfllmf"}
22
- converted_params = call(params, coerce_date_times: true)
30
+ invalid_datetime = "llmfllmf"
31
+ params = { "update_time" => invalid_datetime}
32
+ call(params, coerce_date_times: true)
23
33
 
24
- assert_nil converted_params["update_time"]
34
+ assert_equal invalid_datetime, params["update_time"]
35
+ end
36
+
37
+ it "pass array property" do
38
+ params = {
39
+ "array_property" => [
40
+ {
41
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
42
+ "per_page" => 1,
43
+ "nested_coercer_object" => {
44
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
45
+ "threshold" => 1.5
46
+ },
47
+ "nested_no_coercer_object" => {
48
+ "per_page" => 1,
49
+ "threshold" => 1.5
50
+ },
51
+ "nested_coercer_array" => [
52
+ {
53
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
54
+ "threshold" => 1.5
55
+ }
56
+ ],
57
+ "nested_no_coercer_array" => [
58
+ {
59
+ "per_page" => 1,
60
+ "threshold" => 1.5
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
66
+ "per_page" => 1,
67
+ "threshold" => 1.5
68
+ },
69
+ {
70
+ "threshold" => 1.5,
71
+ "per_page" => 1
72
+ }
73
+ ],
74
+ }
75
+ call(params, coerce_date_times: true, coerce_recursive: true)
76
+
77
+ first_data = params["array_property"][0]
78
+ assert_kind_of DateTime, first_data["update_time"]
79
+ assert_kind_of Integer, first_data["per_page"]
80
+
81
+ second_data = params["array_property"][1]
82
+ assert_kind_of DateTime, second_data["update_time"]
83
+ assert_kind_of Integer, second_data["per_page"]
84
+ assert_kind_of Float, second_data["threshold"]
85
+
86
+ third_data = params["array_property"][1]
87
+ assert_kind_of Integer, third_data["per_page"]
88
+ assert_kind_of Float, third_data["threshold"]
89
+
90
+ assert_kind_of DateTime, first_data["nested_coercer_object"]["update_time"]
91
+ assert_kind_of Float, first_data["nested_coercer_object"]["threshold"]
92
+
93
+ assert_kind_of Integer, first_data["nested_no_coercer_object"]["per_page"]
94
+ assert_kind_of Float, first_data["nested_no_coercer_object"]["threshold"]
95
+
96
+ assert_kind_of DateTime, first_data["nested_coercer_array"].first["update_time"]
97
+ assert_kind_of Float, first_data["nested_coercer_array"].first["threshold"]
98
+
99
+ assert_kind_of Integer, first_data["nested_no_coercer_array"].first["per_page"]
100
+ assert_kind_of Float, first_data["nested_no_coercer_array"].first["threshold"]
25
101
  end
26
102
 
27
103
  private
28
104
 
105
+ class HashLikeObject < Hash; end
106
+
29
107
  def call(params, options={})
30
108
  link = Committee::Drivers::HyperSchema::Link.new(@link)
31
- Committee::ParameterCoercer.new(params, link.schema, options).call
109
+ Committee::ParameterCoercer.new(params, link.schema, options).call!
32
110
  end
33
111
  end
@@ -9,65 +9,122 @@ describe Committee::StringParamsCoercer do
9
9
  end
10
10
 
11
11
  it "doesn't coerce params not in the schema" do
12
- data = {"owner" => "admin"}
13
- assert_equal({}, call(data))
12
+ check_convert("onwer", "admin", "admin")
14
13
  end
15
14
 
16
15
  it "skips values for string param" do
17
- data = {"name" => "foo"}
18
- assert_equal({}, call(data))
16
+ check_convert("name", "foo", "foo")
19
17
  end
20
18
 
21
19
  it "coerces valid values for boolean param" do
22
- data = {"deleted" => "true"}
23
- assert_equal({"deleted" => true}, call(data))
24
- data = {"deleted" => "false"}
25
- assert_equal({"deleted" => false}, call(data))
26
- data = {"deleted" => "1"}
27
- assert_equal({"deleted" => true}, call(data))
28
- data = {"deleted" => "0"}
29
- assert_equal({"deleted" => false}, call(data))
20
+ check_convert("deleted", "true", true)
21
+ check_convert("deleted", "false", false)
22
+ check_convert("deleted", "1", true)
23
+ check_convert("deleted", "0", false)
30
24
  end
31
25
 
32
26
  it "skips invalid values for boolean param" do
33
- data = {"deleted" => "foo"}
34
- assert_equal({}, call(data))
27
+ check_convert("deleted", "foo", "foo")
35
28
  end
36
29
 
37
30
  it "coerces valid values for integer param" do
38
- data = {"per_page" => "3"}
39
- assert_equal({"per_page" => 3}, call(data))
31
+ check_convert("per_page", "3", 3)
40
32
  end
41
33
 
42
34
  it "skips invalid values for integer param" do
43
- data = {"per_page" => "3.5"}
44
- assert_equal({}, call(data))
45
- data = {"per_page" => "false"}
46
- assert_equal({}, call(data))
47
- data = {"per_page" => ""}
48
- assert_equal({}, call(data))
35
+ check_convert("per_page", "3.5", "3.5")
36
+ check_convert("per_page", "false", "false")
37
+ check_convert("per_page", "", "")
49
38
  end
50
39
 
51
40
  it "coerces valid values for number param" do
52
- data = {"threshold" => "3"}
53
- assert_equal({"threshold" => 3.0}, call(data))
54
- data = {"threshold" => "3.5"}
55
- assert_equal({"threshold" => 3.5}, call(data))
41
+ check_convert("threshold", "3", 3.0)
42
+ check_convert("threshold", "3.5", 3.5)
56
43
  end
57
44
 
58
45
  it "skips invalid values for number param" do
59
- data = {"threshold" => "false"}
60
- assert_equal({}, call(data))
46
+ check_convert("threshold", "false", "false")
61
47
  end
62
48
 
63
49
  it "coerces valid values for null param" do
64
- data = {"threshold" => ""}
65
- assert_equal({"threshold" => nil}, call(data))
50
+ check_convert("threshold", "", nil)
51
+ end
52
+
53
+ it "pass array property" do
54
+ params = {
55
+ "array_property" => [
56
+ {
57
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
58
+ "per_page" => "1",
59
+ "nested_coercer_object" => {
60
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
61
+ "threshold" => "1.5"
62
+ },
63
+ "nested_no_coercer_object" => {
64
+ "per_page" => "1",
65
+ "threshold" => "1.5"
66
+ },
67
+ "nested_coercer_array" => [
68
+ {
69
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
70
+ "threshold" => "1.5"
71
+ }
72
+ ],
73
+ "nested_no_coercer_array" => [
74
+ {
75
+ "per_page" => "1",
76
+ "threshold" => "1.5"
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "update_time" => "2016-04-01T16:00:00.000+09:00",
82
+ "per_page" => "1",
83
+ "threshold" => "1.5"
84
+ },
85
+ {
86
+ "threshold" => "1.5",
87
+ "per_page" => "1"
88
+ }
89
+ ],
90
+ }
91
+ call(params, coerce_recursive: true)
92
+
93
+ first_data = params["array_property"][0]
94
+ assert_kind_of String, first_data["update_time"]
95
+ assert_kind_of Integer, first_data["per_page"]
96
+
97
+ second_data = params["array_property"][1]
98
+ assert_kind_of String, second_data["update_time"]
99
+ assert_kind_of Integer, second_data["per_page"]
100
+ assert_kind_of Float, second_data["threshold"]
101
+
102
+ third_data = params["array_property"][1]
103
+ assert_kind_of Integer, third_data["per_page"]
104
+ assert_kind_of Float, third_data["threshold"]
105
+
106
+ assert_kind_of String, first_data["nested_coercer_object"]["update_time"]
107
+ assert_kind_of Float, first_data["nested_coercer_object"]["threshold"]
108
+
109
+ assert_kind_of Integer, first_data["nested_no_coercer_object"]["per_page"]
110
+ assert_kind_of Float, first_data["nested_no_coercer_object"]["threshold"]
111
+
112
+ assert_kind_of String, first_data["nested_coercer_array"].first["update_time"]
113
+ assert_kind_of Float, first_data["nested_coercer_array"].first["threshold"]
114
+
115
+ assert_kind_of Integer, first_data["nested_no_coercer_array"].first["per_page"]
116
+ assert_kind_of Float, first_data["nested_no_coercer_array"].first["threshold"]
66
117
  end
67
118
 
68
119
  private
69
120
 
70
- def call(data)
71
- Committee::StringParamsCoercer.new(data, @link.schema).call
121
+ def check_convert(key, before_value, after_value)
122
+ data = {key => before_value}
123
+ call(data)
124
+ assert_equal(data[key], after_value)
125
+ end
126
+
127
+ def call(data, options={})
128
+ Committee::StringParamsCoercer.new(data, @link.schema, options).call!
72
129
  end
73
130
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: committee
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre8
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandur
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-05-27 00:00:00.000000000 Z
12
+ date: 2017-09-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_schema
@@ -207,12 +207,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
207
207
  version: '0'
208
208
  required_rubygems_version: !ruby/object:Gem::Requirement
209
209
  requirements:
210
- - - ">"
210
+ - - ">="
211
211
  - !ruby/object:Gem::Version
212
- version: 1.3.1
212
+ version: '0'
213
213
  requirements: []
214
214
  rubyforge_project:
215
- rubygems_version: 2.5.1
215
+ rubygems_version: 2.6.12
216
216
  signing_key:
217
217
  specification_version: 4
218
218
  summary: A collection of Rack middleware to support JSON Schema.