committee 2.0.0.pre8 → 2.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.
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.