committee 4.3.0 → 4.99.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/committee/drivers/hyper_schema/schema.rb +2 -2
  3. data/lib/committee/drivers/open_api_2/driver.rb +0 -1
  4. data/lib/committee/drivers/open_api_2/schema.rb +2 -2
  5. data/lib/committee/drivers/open_api_3/schema.rb +2 -2
  6. data/lib/committee/drivers/schema.rb +1 -1
  7. data/lib/committee/middleware/base.rb +1 -1
  8. data/lib/committee/middleware/request_validation.rb +0 -3
  9. data/lib/committee/middleware/response_validation.rb +4 -0
  10. data/lib/committee/request_unpacker.rb +46 -60
  11. data/lib/committee/schema_validator/hyper_schema.rb +33 -26
  12. data/lib/committee/schema_validator/open_api_3.rb +34 -20
  13. data/lib/committee/schema_validator/option.rb +26 -5
  14. data/lib/committee/test/methods.rb +11 -4
  15. data/lib/committee/utils.rb +28 -0
  16. data/lib/committee.rb +1 -0
  17. data/test/drivers_test.rb +1 -1
  18. data/test/middleware/request_validation_open_api_3_test.rb +149 -6
  19. data/test/middleware/request_validation_test.rb +13 -0
  20. data/test/middleware/response_validation_open_api_3_test.rb +2 -2
  21. data/test/middleware/response_validation_test.rb +8 -0
  22. data/test/request_unpacker_test.rb +35 -123
  23. data/test/schema_validator/hyper_schema/router_test.rb +2 -2
  24. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +3 -3
  25. data/test/schema_validator/open_api_3/request_validator_test.rb +0 -3
  26. data/test/schema_validator/open_api_3/response_validator_test.rb +1 -1
  27. data/test/test/methods_new_version_test.rb +13 -4
  28. data/test/test/methods_test.rb +6 -4
  29. data/test/test_helper.rb +13 -1
  30. metadata +45 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19c70ee2e436755ddf7b0b59b213ab7c00b60e67ce52520b956b889121b24e4c
4
- data.tar.gz: 06066adc6056231938d36d93a98c5d7318d9c1ff367784265d66c0eb271fb7b6
3
+ metadata.gz: d369a9be7988a151dbd3b7d9f0065cc821ffcdc8e2543b95355b22fb1f93f6b8
4
+ data.tar.gz: 356fa03d1f3405544d7251302f012f48c0587c31c09b60f2509bdf7776e0c95c
5
5
  SHA512:
6
- metadata.gz: bfbcc7aa85c676291125ed16b20badadda3eb8d895b6834cdc884602345c6ed3a052ecbdd381615b8bbca49815d884407cf8cc2f8cbbe05702593b5cc171f568
7
- data.tar.gz: cc454350c3d04969ad3f24c1922b887a6e319cea4f0a869b647ef439dbc9f5f83f3922bde82abdeb0994a540e53d5e68345e76d7291b408e42cd2f5a4df9eec1
6
+ metadata.gz: 6c821b9f35b1eb20ebea532e8cbc901295596136ccdd680c34ee6eed48da8858c2a22a754a52812cc66de43598f90515ec8642753cb4d3e46390dfd3f840b6a4
7
+ data.tar.gz: 6b720c3e1e2c25e7f8682ba4b8db3879d552a943ec7739d6686baa62b5c4985f609643ed43db67b135025d76e7bde7ff767629ae57b5da27b82107dc6a325629
@@ -12,8 +12,8 @@ module Committee
12
12
 
13
13
  attr_reader :validator_option
14
14
 
15
- def build_router(options)
16
- @validator_option = Committee::SchemaValidator::Option.new(options, self, :hyper_schema)
15
+ def build_router(options, is_request)
16
+ @validator_option = Committee::SchemaValidator::Option.new(options, self, :hyper_schema, is_request)
17
17
  Committee::SchemaValidator::HyperSchema::Router.new(self, @validator_option)
18
18
  end
19
19
  end
@@ -156,7 +156,6 @@ module Committee
156
156
 
157
157
  methods.each do |method, link_data|
158
158
  method = method.upcase
159
-
160
159
  link = Link.new
161
160
  link.enc_type = schema.consumes
162
161
  link.href = href
@@ -16,8 +16,8 @@ module Committee
16
16
  attr_accessor :routes
17
17
  attr_reader :validator_option
18
18
 
19
- def build_router(options)
20
- @validator_option = Committee::SchemaValidator::Option.new(options, self, :hyper_schema)
19
+ def build_router(options, is_request)
20
+ @validator_option = Committee::SchemaValidator::Option.new(options, self, :hyper_schema, is_request)
21
21
  Committee::SchemaValidator::HyperSchema::Router.new(self, @validator_option)
22
22
  end
23
23
  end
@@ -23,8 +23,8 @@ module Committee
23
23
  @driver
24
24
  end
25
25
 
26
- def build_router(options)
27
- @validator_option = Committee::SchemaValidator::Option.new(options, self, :open_api_3)
26
+ def build_router(options, is_request)
27
+ @validator_option = Committee::SchemaValidator::Option.new(options, self, :open_api_3, is_request)
28
28
  Committee::SchemaValidator::OpenAPI3::Router.new(self, @validator_option)
29
29
  end
30
30
 
@@ -10,7 +10,7 @@ module Committee
10
10
  raise "needs implementation"
11
11
  end
12
12
 
13
- def build_router(options)
13
+ def build_router(options, is_request)
14
14
  raise "needs implementation"
15
15
  end
16
16
 
@@ -13,7 +13,7 @@ module Committee
13
13
  @raise = options[:raise]
14
14
  @schema = self.class.get_schema(options)
15
15
 
16
- @router = @schema.build_router(options)
16
+ @router = @schema.build_router(options, is_request: Committee::Middleware::RequestValidation == self.class)
17
17
  @accept_request_filter = options[:accept_request_filter] || -> (_) { true }
18
18
  end
19
19
 
@@ -7,9 +7,6 @@ module Committee
7
7
  super
8
8
 
9
9
  @strict = options[:strict]
10
-
11
- # deprecated
12
- @allow_extra = options[:allow_extra]
13
10
  end
14
11
 
15
12
  def handle(request)
@@ -7,6 +7,10 @@ module Committee
7
7
 
8
8
  def initialize(app, options = {})
9
9
  super
10
+
11
+ unless options[:strict].nil?
12
+ Committee.warn_deprecated("Committee: Committee::Middleware::ResponseValidation doesn't support strict option now but we'll support this option. This change break backward compatibility so please remove strict option from ResponseValidation")
13
+ end
10
14
  @validate_success_only = @schema.validator_option.validate_success_only
11
15
  end
12
16
 
@@ -2,84 +2,82 @@
2
2
 
3
3
  module Committee
4
4
  class RequestUnpacker
5
- def initialize(request, options={})
6
- @request = request
5
+ class << self
6
+ # Enable string or symbol key access to the nested params hash.
7
+ #
8
+ # (Copied from Sinatra)
9
+ def indifferent_params(object)
10
+ case object
11
+ when Hash
12
+ new_hash = Committee::Utils.indifferent_hash
13
+ object.each { |key, value| new_hash[key] = indifferent_params(value) }
14
+ new_hash
15
+ when Array
16
+ object.map { |item| indifferent_params(item) }
17
+ else
18
+ object
19
+ end
20
+ end
21
+ end
7
22
 
23
+ def initialize(options={})
8
24
  @allow_form_params = options[:allow_form_params]
9
25
  @allow_get_body = options[:allow_get_body]
10
26
  @allow_query_params = options[:allow_query_params]
11
- @coerce_form_params = options[:coerce_form_params]
12
27
  @optimistic_json = options[:optimistic_json]
13
- @schema_validator = options[:schema_validator]
14
28
  end
15
29
 
16
- def call
30
+ # reutrn params and is_form_params
31
+ def unpack_request_params(request)
17
32
  # if Content-Type is empty or JSON, and there was a request body, try to
18
33
  # interpret it as JSON
19
- params = if !@request.media_type || @request.media_type =~ %r{application/(?:.*\+)?json}
20
- parse_json
34
+ params = if !request.media_type || request.media_type =~ %r{application/(?:.*\+)?json}
35
+ parse_json(request)
21
36
  elsif @optimistic_json
22
37
  begin
23
- parse_json
38
+ parse_json(request)
24
39
  rescue JSON::ParserError
25
40
  nil
26
41
  end
27
42
  end
28
43
 
29
- params = if params
30
- params
31
- elsif @allow_form_params && %w[application/x-www-form-urlencoded multipart/form-data].include?(@request.media_type)
44
+ return [params, false] if params
45
+
46
+ if @allow_form_params && %w[application/x-www-form-urlencoded multipart/form-data].include?(request.media_type)
32
47
  # Actually, POST means anything in the request body, could be from
33
48
  # PUT or PATCH too. Silly Rack.
34
- p = @request.POST
35
-
36
- @schema_validator.coerce_form_params(p) if @coerce_form_params
37
-
38
- p
39
- else
40
- {}
49
+ return [request.POST, true] if request.POST
41
50
  end
42
51
 
43
- if @allow_query_params
44
- [indifferent_params(@request.GET).merge(params), headers]
45
- else
46
- [params, headers]
47
- end
52
+ [{}, false]
48
53
  end
49
54
 
50
- private
51
-
52
- # Creates a Hash with indifferent access.
53
- #
54
- # (Copied from Sinatra)
55
- def indifferent_hash
56
- Hash.new { |hash,key| hash[key.to_s] if Symbol === key }
55
+ def unpack_query_params(request)
56
+ @allow_query_params ? self.class.indifferent_params(request.GET) : {}
57
57
  end
58
58
 
59
- # Enable string or symbol key access to the nested params hash.
60
- #
61
- # (Copied from Sinatra)
62
- def indifferent_params(object)
63
- case object
64
- when Hash
65
- new_hash = indifferent_hash
66
- object.each { |key, value| new_hash[key] = indifferent_params(value) }
67
- new_hash
68
- when Array
69
- object.map { |item| indifferent_params(item) }
70
- else
71
- object
59
+ def unpack_headers(request)
60
+ env = request.env
61
+ base = env.keys.grep(/HTTP_/).inject({}) do |headers, key|
62
+ headerized_key = key.gsub(/^HTTP_/, '').gsub(/_/, '-')
63
+ headers[headerized_key] = env[key]
64
+ headers
72
65
  end
66
+
67
+ base['Content-Type'] = env['CONTENT_TYPE'] if env['CONTENT_TYPE']
68
+ base
73
69
  end
74
70
 
75
- def parse_json
76
- return nil if @request.request_method == "GET" && !@allow_get_body
71
+ private
72
+
73
+ def parse_json(request)
74
+ return nil if request.request_method == "GET" && !@allow_get_body
77
75
 
78
- body = @request.body.read
76
+ body = request.body.read
79
77
  # if request body is empty, we just have empty params
80
78
  return nil if body.length == 0
81
79
 
82
- @request.body.rewind
80
+ request.body.rewind
83
81
  hash = JSON.parse(body)
84
82
  # We want a hash specifically. '42', 42, and [42] will all be
85
83
  # decoded properly, but we can't use them here.
@@ -87,19 +85,7 @@ module Committee
87
85
  raise BadRequest,
88
86
  "Invalid JSON input. Require object with parameters as keys."
89
87
  end
90
- indifferent_params(hash)
91
- end
92
-
93
- def headers
94
- env = @request.env
95
- base = env.keys.grep(/HTTP_/).inject({}) do |headers, key|
96
- headerized_key = key.gsub(/^HTTP_/, '').gsub(/_/, '-')
97
- headers[headerized_key] = env[key]
98
- headers
99
- end
100
-
101
- base['Content-Type'] = env['CONTENT_TYPE'] if env['CONTENT_TYPE']
102
- base
88
+ self.class.indifferent_params(hash)
103
89
  end
104
90
  end
105
91
  end
@@ -11,18 +11,8 @@ module Committee
11
11
  end
12
12
 
13
13
  def request_validate(request)
14
- # Attempts to coerce parameters that appear in a link's URL to Ruby
15
- # types that can be validated with a schema.
16
- param_matches_hash = validator_option.coerce_path_params ? coerce_path_params : {}
17
-
18
- # Attempts to coerce parameters that appear in a query string to Ruby
19
- # types that can be validated with a schema.
20
- coerce_query_params(request) if validator_option.coerce_query_params
21
-
22
14
  request_unpack(request)
23
15
 
24
- request.env[validator_option.params_key].merge!(param_matches_hash) if param_matches_hash
25
-
26
16
  request_schema_validation(request)
27
17
  parameter_coerce!(request, link, validator_option.params_key)
28
18
  parameter_coerce!(request, link, "rack.request.query_hash") if link_exist? && !request.GET.nil? && !link.schema.nil?
@@ -50,16 +40,10 @@ module Committee
50
40
  !link.nil?
51
41
  end
52
42
 
53
- def coerce_form_params(parameter)
54
- return unless link_exist?
55
- return unless link.schema
56
- Committee::SchemaValidator::HyperSchema::StringParamsCoercer.new(parameter, link.schema).call!
57
- end
58
-
59
43
  private
60
44
 
61
45
  def coerce_path_params
62
- return unless link_exist?
46
+ return {} unless link_exist?
63
47
 
64
48
  Committee::SchemaValidator::HyperSchema::StringParamsCoercer.new(param_matches, link.schema, coerce_recursive: validator_option.coerce_recursive).call!
65
49
  param_matches
@@ -73,15 +57,38 @@ module Committee
73
57
  end
74
58
 
75
59
  def request_unpack(request)
76
- request.env[validator_option.params_key], request.env[validator_option.headers_key] = Committee::RequestUnpacker.new(
77
- request,
78
- allow_form_params: validator_option.allow_form_params,
79
- allow_get_body: validator_option.allow_get_body,
80
- allow_query_params: validator_option.allow_query_params,
81
- coerce_form_params: validator_option.coerce_form_params,
82
- optimistic_json: validator_option.optimistic_json,
83
- schema_validator: self
84
- ).call
60
+ unpacker = Committee::RequestUnpacker.new(
61
+ allow_form_params: validator_option.allow_form_params,
62
+ allow_get_body: validator_option.allow_get_body,
63
+ allow_query_params: validator_option.allow_query_params,
64
+ optimistic_json: validator_option.optimistic_json,
65
+ )
66
+
67
+ request.env[validator_option.headers_key] = unpacker.unpack_headers(request)
68
+
69
+ # Attempts to coerce parameters that appear in a link's URL to Ruby
70
+ # types that can be validated with a schema.
71
+ param_matches_hash = validator_option.coerce_path_params ? coerce_path_params : {}
72
+
73
+ # Attempts to coerce parameters that appear in a query string to Ruby
74
+ # types that can be validated with a schema.
75
+ coerce_query_params(request) if validator_option.coerce_query_params
76
+
77
+ query_param = unpacker.unpack_query_params(request)
78
+ request_param, is_form_params = unpacker.unpack_request_params(request)
79
+ coerce_form_params(request_param) if validator_option.coerce_form_params && is_form_params
80
+ request.env[validator_option.request_body_hash_key] = request_param
81
+
82
+ request.env[validator_option.params_key] = Committee::Utils.indifferent_hash
83
+ request.env[validator_option.params_key].merge!(Committee::Utils.deep_copy(query_param))
84
+ request.env[validator_option.params_key].merge!(Committee::Utils.deep_copy(request_param))
85
+ request.env[validator_option.params_key].merge!(Committee::Utils.deep_copy(param_matches_hash))
86
+ end
87
+
88
+ def coerce_form_params(parameter)
89
+ return unless link_exist?
90
+ return unless link.schema
91
+ Committee::SchemaValidator::HyperSchema::StringParamsCoercer.new(parameter, link.schema).call!
85
92
  end
86
93
 
87
94
  def request_schema_validation(request)
@@ -14,12 +14,7 @@ module Committee
14
14
  def request_validate(request)
15
15
  return unless link_exist?
16
16
 
17
- path_params = validator_option.coerce_path_params ? coerce_path_params : {}
18
-
19
17
  request_unpack(request)
20
-
21
- request.env[validator_option.params_key]&.merge!(path_params) unless path_params.empty?
22
-
23
18
  request_schema_validation(request)
24
19
 
25
20
  copy_coerced_data_to_query_hash(request)
@@ -49,16 +44,13 @@ module Committee
49
44
  !@operation_object.nil?
50
45
  end
51
46
 
52
- def coerce_form_params(_parameter)
53
- # Empty because request_schema_validation checks and coerces
54
- end
55
-
56
47
  private
57
48
 
58
49
  attr_reader :validator_option
59
50
 
60
51
  def coerce_path_params
61
- @operation_object.coerce_path_parameter(@validator_option)
52
+ return Committee::Utils.indifferent_hash unless validator_option.coerce_path_params
53
+ Committee::RequestUnpacker.indifferent_params(@operation_object.coerce_path_parameter(@validator_option))
62
54
  end
63
55
 
64
56
  def request_schema_validation(request)
@@ -73,22 +65,44 @@ module Committee
73
65
  end
74
66
 
75
67
  def request_unpack(request)
76
- request.env[validator_option.params_key], request.env[validator_option.headers_key] = Committee::RequestUnpacker.new(
77
- request,
78
- allow_form_params: validator_option.allow_form_params,
79
- allow_get_body: validator_option.allow_get_body,
80
- allow_query_params: validator_option.allow_query_params,
81
- coerce_form_params: validator_option.coerce_form_params,
82
- optimistic_json: validator_option.optimistic_json,
83
- schema_validator: self
84
- ).call
68
+ unpacker = Committee::RequestUnpacker.new(
69
+ allow_form_params: validator_option.allow_form_params,
70
+ allow_get_body: validator_option.allow_get_body,
71
+ allow_query_params: validator_option.allow_query_params,
72
+ optimistic_json: validator_option.optimistic_json,
73
+ )
74
+
75
+ request.env[validator_option.headers_key] = unpacker.unpack_headers(request)
76
+
77
+ request_param, is_form_params = unpacker.unpack_request_params(request)
78
+ request.env[validator_option.request_body_hash_key] = request_param
79
+ request.env[validator_option.path_hash_key] = coerce_path_params
80
+
81
+ query_param = unpacker.unpack_query_params(request)
82
+
83
+ order = if validator_option.parameter_overwite_by_rails_rule
84
+ # (high priority) path_hash_key -> query_param -> request_body_hash
85
+ [request.env[validator_option.request_body_hash_key], query_param, request.env[validator_option.path_hash_key]]
86
+ else
87
+ # (high priority) path_hash_key -> request_body_hash -> query_param
88
+ [query_param, request.env[validator_option.request_body_hash_key], request.env[validator_option.path_hash_key]]
89
+ end
90
+
91
+ request.env[validator_option.params_key] = Committee::Utils.indifferent_hash
92
+ order.each do |param|
93
+ request.env[validator_option.params_key].merge!(Committee::Utils.deep_copy(param))
94
+ end
85
95
  end
86
96
 
87
97
  def copy_coerced_data_to_query_hash(request)
88
98
  return if request.env["rack.request.query_hash"].nil? || request.env["rack.request.query_hash"].empty?
89
99
 
100
+ query_hash_key = @validator_option.query_hash_key
101
+ return unless query_hash_key
102
+
103
+ request.env[query_hash_key] = {} unless request.env[query_hash_key]
90
104
  request.env["rack.request.query_hash"].keys.each do |k|
91
- request.env["rack.request.query_hash"][k] = request.env[validator_option.params_key][k]
105
+ request.env[query_hash_key][k] = request.env[validator_option.params_key][k]
92
106
  end
93
107
  end
94
108
  end
@@ -16,17 +16,30 @@ module Committee
16
16
  :coerce_recursive,
17
17
  :optimistic_json,
18
18
  :validate_success_only,
19
- :parse_response_by_content_type
19
+ :parse_response_by_content_type,
20
+ :parameter_overwite_by_rails_rule
20
21
 
21
22
  # Non-boolean options:
22
23
  attr_reader :headers_key,
23
24
  :params_key,
25
+ :query_hash_key,
26
+ :request_body_hash_key,
27
+ :path_hash_key,
24
28
  :prefix
25
29
 
26
- def initialize(options, schema, schema_type)
30
+ def initialize(options, schema, schema_type, is_request)
27
31
  # Non-boolean options
28
- @headers_key = options[:headers_key] || "committee.headers"
29
- @params_key = options[:params_key] || "committee.params"
32
+ @headers_key = options[:headers_key] || "committee.headers"
33
+ @params_key = options[:params_key] || "committee.params"
34
+ @query_hash_key = if options[:query_hash_key].nil?
35
+ Committee.warn_deprecated('Committee: please set query_hash_key = "rack.request.query_hash" because we\'ll change default value to "committee.query_hash" in next major version.')
36
+ 'rack.request.query_hash'
37
+ else
38
+ options.fetch(:query_hash_key)
39
+ end
40
+ @path_hash_key = options[:path_hash_key] || "committee.path_hash"
41
+ @request_body_hash_key = options[:request_body_hash_key] || "committee.request_body_hash"
42
+
30
43
  @prefix = options[:prefix]
31
44
 
32
45
  # Boolean options and have a common value by default
@@ -37,11 +50,19 @@ module Committee
37
50
  @coerce_recursive = options.fetch(:coerce_recursive, true)
38
51
  @optimistic_json = options.fetch(:optimistic_json, false)
39
52
  @parse_response_by_content_type = if options[:parse_response_by_content_type].nil?
40
- Committee.warn_deprecated('Committee: please set parse_response_by_content_type = false because we\'ll change default value in next major version.')
53
+ if !is_request
54
+ Committee.warn_deprecated('Committee: please set parse_response_by_content_type = false because we\'ll change default value in next major version.')
55
+ end
41
56
  false
42
57
  else
43
58
  options.fetch(:parse_response_by_content_type)
44
59
  end
60
+ @parameter_overwite_by_rails_rule = if options[:parameter_overwite_by_rails_rule].nil?
61
+ Committee.warn_deprecated('Committee: please set parameter_overwite_by_rails_rule = false because we\'ll change default value to "true" in next major version.')
62
+ false
63
+ else
64
+ options.fetch(:parameter_overwite_by_rails_rule)
65
+ end
45
66
 
46
67
  # Boolean options and have a different value by default
47
68
  @allow_get_body = options.fetch(:allow_get_body, schema.driver.default_allow_get_body)
@@ -3,9 +3,9 @@
3
3
  module Committee
4
4
  module Test
5
5
  module Methods
6
- def assert_schema_conform
6
+ def assert_schema_conform(expected_status = nil)
7
7
  assert_request_schema_confirm unless old_behavior
8
- assert_response_schema_confirm
8
+ assert_response_schema_confirm(expected_status)
9
9
  end
10
10
 
11
11
  def assert_request_schema_confirm
@@ -17,7 +17,7 @@ module Committee
17
17
  schema_validator.request_validate(request_object)
18
18
  end
19
19
 
20
- def assert_response_schema_confirm
20
+ def assert_response_schema_confirm(expected_status = nil)
21
21
  unless schema_validator.link_exist?
22
22
  response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema (prefix: #{committee_options[:prefix].inspect})."
23
23
  raise Committee::InvalidResponse.new(response)
@@ -25,6 +25,13 @@ module Committee
25
25
 
26
26
  status, headers, body = response_data
27
27
 
28
+ if expected_status.nil?
29
+ Committee.warn_deprecated('Pass expected response status code to check it against the corresponding schema explicitly.')
30
+ elsif expected_status != status
31
+ response = "Expected `#{expected_status}` status code, but it was `#{status}`."
32
+ raise Committee::InvalidResponse.new(response)
33
+ end
34
+
28
35
  if schema_coverage
29
36
  operation_object = router.operation_object(request_object)
30
37
  schema_coverage&.update_response_coverage!(operation_object.original_path, operation_object.http_method, status)
@@ -54,7 +61,7 @@ module Committee
54
61
  end
55
62
 
56
63
  def router
57
- @router ||= schema.build_router(committee_options)
64
+ @router ||= schema.build_router(committee_options, true)
58
65
  end
59
66
 
60
67
  def schema_validator
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Utils
5
+ # Creates a Hash with indifferent access.
6
+ #
7
+ # (Copied from Sinatra)
8
+ def self.indifferent_hash
9
+ Hash.new { |hash,key| hash[key.to_s] if Symbol === key }
10
+ end
11
+
12
+ def self.deep_copy(from)
13
+ if from.is_a?(Hash)
14
+ h = Committee::Utils.indifferent_hash
15
+ from.each_pair do |k, v|
16
+ h[k] = deep_copy(v)
17
+ end
18
+ return h
19
+ end
20
+
21
+ if from.is_a?(Array)
22
+ return from.map{ |v| deep_copy(v) }
23
+ end
24
+
25
+ return from
26
+ end
27
+ end
28
+ end
data/lib/committee.rb CHANGED
@@ -20,6 +20,7 @@ module Committee
20
20
  end
21
21
  end
22
22
 
23
+ require_relative "committee/utils"
23
24
  require_relative "committee/drivers"
24
25
  require_relative "committee/errors"
25
26
  require_relative "committee/middleware"
data/test/drivers_test.rb CHANGED
@@ -125,7 +125,7 @@ end
125
125
  describe Committee::Drivers::Schema do
126
126
  SCHEMA_METHODS = {
127
127
  driver: [],
128
- build_router: [validator_option: nil, prefix: nil]
128
+ build_router: [[validator_option: nil, prefix: nil], true]
129
129
  }
130
130
 
131
131
  it "has a set of abstract methods" do