grape 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/CONTRIBUTING.md +31 -1
  4. data/README.md +38 -8
  5. data/grape.gemspec +2 -2
  6. data/lib/grape/api.rb +2 -2
  7. data/lib/grape/content_types.rb +2 -8
  8. data/lib/grape/dsl/desc.rb +3 -2
  9. data/lib/grape/dsl/inside_route.rb +6 -6
  10. data/lib/grape/dsl/parameters.rb +6 -1
  11. data/lib/grape/dsl/request_response.rb +3 -2
  12. data/lib/grape/dsl/settings.rb +2 -6
  13. data/lib/grape/endpoint.rb +21 -19
  14. data/lib/grape/error_formatter/base.rb +1 -1
  15. data/lib/grape/exceptions/base.rb +4 -3
  16. data/lib/grape/exceptions/missing_group_type.rb +1 -6
  17. data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
  18. data/lib/grape/exceptions/validation_errors.rb +1 -6
  19. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
  20. data/lib/grape/extensions/hash.rb +4 -7
  21. data/lib/grape/extensions/hashie/mash.rb +3 -3
  22. data/lib/grape/formatter/serializable_hash.rb +7 -7
  23. data/lib/grape/middleware/auth/base.rb +1 -1
  24. data/lib/grape/middleware/error.rb +1 -1
  25. data/lib/grape/middleware/formatter.rb +1 -1
  26. data/lib/grape/middleware/stack.rb +1 -1
  27. data/lib/grape/middleware/versioner/header.rb +11 -19
  28. data/lib/grape/request.rb +1 -1
  29. data/lib/grape/router/attribute_translator.rb +1 -1
  30. data/lib/grape/router/route.rb +1 -3
  31. data/lib/grape/types/invalid_value.rb +8 -0
  32. data/lib/grape/util/cache.rb +1 -1
  33. data/lib/grape/util/lazy_value.rb +3 -11
  34. data/lib/grape/util/strict_hash_configuration.rb +3 -4
  35. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  36. data/lib/grape/validations/params_scope.rb +9 -3
  37. data/lib/grape/validations/single_attribute_iterator.rb +3 -1
  38. data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
  39. data/lib/grape/validations/types/invalid_value.rb +0 -7
  40. data/lib/grape/validations/validators/base.rb +9 -20
  41. data/lib/grape/validations/validators/default_validator.rb +2 -20
  42. data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
  43. data/lib/grape/validations/validators/values_validator.rb +14 -5
  44. data/lib/grape/version.rb +1 -1
  45. data/lib/grape.rb +19 -3
  46. data/spec/grape/api/custom_validations_spec.rb +14 -57
  47. data/spec/grape/api_remount_spec.rb +36 -0
  48. data/spec/grape/api_spec.rb +15 -21
  49. data/spec/grape/dsl/desc_spec.rb +84 -85
  50. data/spec/grape/dsl/inside_route_spec.rb +6 -10
  51. data/spec/grape/dsl/request_response_spec.rb +21 -2
  52. data/spec/grape/endpoint_spec.rb +11 -10
  53. data/spec/grape/exceptions/body_parse_errors_spec.rb +40 -0
  54. data/spec/grape/exceptions/invalid_accept_header_spec.rb +3 -0
  55. data/spec/grape/exceptions/missing_group_type_spec.rb +5 -9
  56. data/spec/grape/exceptions/unsupported_group_type_spec.rb +5 -9
  57. data/spec/grape/grape_spec.rb +9 -0
  58. data/spec/grape/integration/rack_spec.rb +6 -5
  59. data/spec/grape/middleware/base_spec.rb +7 -5
  60. data/spec/grape/middleware/formatter_spec.rb +7 -7
  61. data/spec/grape/request_spec.rb +4 -14
  62. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +6 -8
  63. data/spec/grape/validations/single_attribute_iterator_spec.rb +8 -9
  64. data/spec/grape/validations/validators/base_spec.rb +38 -0
  65. data/spec/grape/validations/validators/values_spec.rb +56 -0
  66. data/spec/grape/validations_spec.rb +36 -12
  67. data/spec/shared/deprecated_class_examples.rb +16 -0
  68. metadata +112 -114
  69. data/lib/grape/config.rb +0 -34
  70. data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
  71. data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
  72. data/spec/grape/config_spec.rb +0 -17
  73. data/spec/grape/dsl/configuration_spec.rb +0 -14
  74. data/spec/grape/validations/attributes_iterator_spec.rb +0 -4
@@ -15,24 +15,24 @@ module Grape
15
15
  private
16
16
 
17
17
  def serializable?(object)
18
- object.respond_to?(:serializable_hash) || (object.is_a?(Array) && object.all? { |o| o.respond_to? :serializable_hash }) || object.is_a?(Hash)
18
+ object.respond_to?(:serializable_hash) || array_serializable?(object) || object.is_a?(Hash)
19
19
  end
20
20
 
21
21
  def serialize(object)
22
22
  if object.respond_to? :serializable_hash
23
23
  object.serializable_hash
24
- elsif object.is_a?(Array) && object.all? { |o| o.respond_to? :serializable_hash }
24
+ elsif array_serializable?(object)
25
25
  object.map(&:serializable_hash)
26
26
  elsif object.is_a?(Hash)
27
- h = {}
28
- object.each_pair do |k, v|
29
- h[k] = serialize(v)
30
- end
31
- h
27
+ object.transform_values { |v| serialize(v) }
32
28
  else
33
29
  object
34
30
  end
35
31
  end
32
+
33
+ def array_serializable?(object)
34
+ object.is_a?(Array) && object.all? { |o| o.respond_to? :serializable_hash }
35
+ end
36
36
  end
37
37
  end
38
38
  end
@@ -28,7 +28,7 @@ module Grape
28
28
 
29
29
  strategy_info = Grape::Middleware::Auth::Strategies[options[:type]]
30
30
 
31
- throw(:error, status: 401, message: 'API Authorization Failed.') unless strategy_info.present?
31
+ throw(:error, status: 401, message: 'API Authorization Failed.') if strategy_info.blank?
32
32
 
33
33
  strategy = strategy_info.create(@app, options) do |*args|
34
34
  auth_proc_context.instance_exec(*args, &auth_proc)
@@ -109,7 +109,7 @@ module Grape
109
109
  return :error_response if klass == Grape::Exceptions::InvalidVersionHeader
110
110
  return unless options[:rescue_grape_exceptions] || !options[:rescue_all]
111
111
 
112
- :error_response
112
+ options[:grape_exceptions_rescue_handler] || :error_response
113
113
  end
114
114
 
115
115
  def rescue_handler_for_any_class(klass)
@@ -103,7 +103,7 @@ module Grape
103
103
  begin
104
104
  body = (env[Grape::Env::API_REQUEST_BODY] = parser.call(body, env))
105
105
  if body.is_a?(Hash)
106
- env[Grape::Env::RACK_REQUEST_FORM_HASH] = if env[Grape::Env::RACK_REQUEST_FORM_HASH]
106
+ env[Grape::Env::RACK_REQUEST_FORM_HASH] = if env.key?(Grape::Env::RACK_REQUEST_FORM_HASH)
107
107
  env[Grape::Env::RACK_REQUEST_FORM_HASH].merge(body)
108
108
  else
109
109
  body
@@ -95,7 +95,7 @@ module Grape
95
95
 
96
96
  # @return [Rack::Builder] the builder object with our middlewares applied
97
97
  def build(builder = Rack::Builder.new)
98
- others.shift(others.size).each(&method(:merge_with))
98
+ others.shift(others.size).each { |m| merge_with(m) }
99
99
  middlewares.each do |m|
100
100
  m.use_in(builder)
101
101
  end
@@ -57,8 +57,7 @@ module Grape
57
57
  end
58
58
 
59
59
  def strict_version_vendor_accept_header_presence_check
60
- return unless versions.present?
61
- return if an_accept_header_with_version_and_vendor_is_present?
60
+ return if versions.blank? || an_accept_header_with_version_and_vendor_is_present?
62
61
 
63
62
  fail_with_invalid_accept_header!('API vendor or version not found.')
64
63
  end
@@ -101,25 +100,18 @@ module Grape
101
100
  end
102
101
 
103
102
  def available_media_types
104
- available_media_types = []
105
-
106
- content_types.each_key do |extension|
107
- versions.reverse_each do |version|
108
- available_media_types += [
109
- "application/vnd.#{vendor}-#{version}+#{extension}",
110
- "application/vnd.#{vendor}-#{version}"
111
- ]
103
+ [].tap do |available_media_types|
104
+ content_types.each_key do |extension|
105
+ versions.reverse_each do |version|
106
+ available_media_types << "application/vnd.#{vendor}-#{version}+#{extension}"
107
+ available_media_types << "application/vnd.#{vendor}-#{version}"
108
+ end
109
+ available_media_types << "application/vnd.#{vendor}+#{extension}"
112
110
  end
113
- available_media_types << "application/vnd.#{vendor}+#{extension}"
114
- end
115
-
116
- available_media_types << "application/vnd.#{vendor}"
117
111
 
118
- content_types.each_value do |media_type|
119
- available_media_types << media_type
112
+ available_media_types << "application/vnd.#{vendor}"
113
+ available_media_types.concat(content_types.values.flatten)
120
114
  end
121
-
122
- available_media_types.flatten
123
115
  end
124
116
 
125
117
  def headers_contain_wrong_vendor?
@@ -130,7 +122,7 @@ module Grape
130
122
 
131
123
  def headers_contain_wrong_version?
132
124
  header.values.all? do |header_value|
133
- version?(header_value) && !versions.include?(request_version(header_value))
125
+ version?(header_value) && versions.exclude?(request_version(header_value))
134
126
  end
135
127
  end
136
128
 
data/lib/grape/request.rb CHANGED
@@ -47,7 +47,7 @@ module Grape
47
47
  end
48
48
 
49
49
  def transform_header(header)
50
- -header[5..-1].split('_').each(&:capitalize!).join('-')
50
+ -header[5..].split('_').each(&:capitalize!).join('-')
51
51
  end
52
52
  end
53
53
  end
@@ -39,7 +39,7 @@ module Grape
39
39
 
40
40
  def method_missing(method_name, *args)
41
41
  if setter?(method_name[-1])
42
- attributes[method_name[0..-1]] = *args
42
+ attributes[method_name[0..]] = *args
43
43
  else
44
44
  attributes[method_name]
45
45
  end
@@ -84,9 +84,7 @@ module Grape
84
84
  path, line = *location.scan(SOURCE_LOCATION_REGEXP).first
85
85
  path = File.realpath(path) if Pathname.new(path).relative?
86
86
  expected ||= name
87
- warn <<~WARNING
88
- #{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.
89
- WARNING
87
+ ActiveSupport::Deprecation.warn("#{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.")
90
88
  end
91
89
  end
92
90
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # only exists to make it shorter for external use
4
+ module Grape
5
+ module Types
6
+ InvalidValue = Class.new(Grape::Validations::Types::InvalidValue)
7
+ end
8
+ end
@@ -1,4 +1,4 @@
1
- # frozen_String_literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'singleton'
4
4
  require 'forwardable'
@@ -70,29 +70,21 @@ module Grape
70
70
  end
71
71
 
72
72
  def evaluate
73
- evaluated = []
74
- @value_hash.each_with_index do |value, index|
75
- evaluated[index] = value.evaluate
76
- end
77
- evaluated
73
+ @value_hash.map(&:evaluate)
78
74
  end
79
75
  end
80
76
 
81
77
  class LazyValueHash < LazyValueEnumerable
82
78
  def initialize(hash)
83
79
  super
84
- @value_hash = {}.with_indifferent_access
80
+ @value_hash = ActiveSupport::HashWithIndifferentAccess.new
85
81
  hash.each do |key, value|
86
82
  self[key] = value
87
83
  end
88
84
  end
89
85
 
90
86
  def evaluate
91
- evaluated = {}.with_indifferent_access
92
- @value_hash.each do |key, value|
93
- evaluated[key] = value.evaluate
94
- end
95
- evaluated
87
+ @value_hash.transform_values(&:evaluate)
96
88
  end
97
89
  end
98
90
  end
@@ -66,11 +66,10 @@ module Grape
66
66
  end
67
67
 
68
68
  define_method :to_hash do
69
- merge_hash = {}
70
- setting_name.each_key { |k| merge_hash[k] = send("#{k}_context").to_hash }
71
-
72
69
  @settings.to_hash.merge(
73
- merge_hash
70
+ setting_name.each_key.with_object({}) do |k, merge_hash|
71
+ merge_hash[k] = send("#{k}_context").to_hash
72
+ end
74
73
  )
75
74
  end
76
75
  end
@@ -6,7 +6,7 @@ module Grape
6
6
  private
7
7
 
8
8
  def yield_attributes(resource_params, _attrs)
9
- yield resource_params, skip?(resource_params)
9
+ yield resource_params unless skip?(resource_params)
10
10
  end
11
11
  end
12
12
  end
@@ -10,6 +10,11 @@ module Grape
10
10
 
11
11
  include Grape::DSL::Parameters
12
12
 
13
+ # There are a number of documentation options on entities that don't have
14
+ # corresponding validators. Since there is nowhere that enumerates them all,
15
+ # we maintain a list of them here and skip looking up validators for them.
16
+ RESERVED_DOCUMENTATION_KEYWORDS = %i[as required param_type is_array format example].freeze
17
+
13
18
  class Attr
14
19
  attr_accessor :key, :scope
15
20
 
@@ -359,7 +364,8 @@ module Grape
359
364
  coerce_type validations, attrs, doc, opts
360
365
 
361
366
  validations.each do |type, options|
362
- next if type == :as
367
+ # Don't try to look up validators for documentation params that don't have one.
368
+ next if RESERVED_DOCUMENTATION_KEYWORDS.include?(type)
363
369
 
364
370
  validate(type, options, attrs, doc, opts)
365
371
  end
@@ -414,7 +420,7 @@ module Grape
414
420
 
415
421
  # but not special JSON types, which
416
422
  # already imply coercion method
417
- return unless [JSON, Array[JSON]].include? validations[:coerce]
423
+ return if [JSON, Array[JSON]].exclude? validations[:coerce]
418
424
 
419
425
  raise ArgumentError, 'coerce_with disallowed for type: JSON'
420
426
  end
@@ -485,7 +491,7 @@ module Grape
485
491
  values_list.each do |values|
486
492
  next if !values || values.is_a?(Proc)
487
493
 
488
- value_types = values.is_a?(Range) ? [values.begin, values.end] : values
494
+ value_types = values.is_a?(Range) ? [values.begin, values.end].compact : values
489
495
  value_types = value_types.map { |type| Grape::API::Boolean.build(type) } if coerce_type == Grape::API::Boolean
490
496
  raise Grape::Exceptions::IncompatibleOptionValues.new(:type, coerce_type, :values, values) unless value_types.all?(coerce_type)
491
497
  end
@@ -6,8 +6,10 @@ module Grape
6
6
  private
7
7
 
8
8
  def yield_attributes(val, attrs)
9
+ return if skip?(val)
10
+
9
11
  attrs.each do |attr_name|
10
- yield val, attr_name, empty?(val), skip?(val)
12
+ yield val, attr_name, empty?(val)
11
13
  end
12
14
  end
13
15
 
@@ -141,7 +141,7 @@ module Grape
141
141
  lambda do |val|
142
142
  method.call(val).tap do |new_val|
143
143
  new_val.map do |item|
144
- item.is_a?(Hash) ? symbolize_keys(item) : item
144
+ item.is_a?(Hash) ? item.deep_symbolize_keys : item
145
145
  end
146
146
  end
147
147
  end
@@ -149,7 +149,7 @@ module Grape
149
149
  # Hash objects are processed directly
150
150
  elsif type == Hash
151
151
  lambda do |val|
152
- symbolize_keys method.call(val)
152
+ method.call(val).deep_symbolize_keys
153
153
  end
154
154
 
155
155
  # Simple types are not processed.
@@ -158,20 +158,6 @@ module Grape
158
158
  method
159
159
  end
160
160
  end
161
-
162
- def symbolize_keys!(hash)
163
- hash.each_key do |key|
164
- hash[key.to_sym] = hash.delete(key) if key.respond_to?(:to_sym)
165
- end
166
- hash
167
- end
168
-
169
- def symbolize_keys(hash)
170
- hash.inject({}) do |new_hash, (key, value)|
171
- new_key = key.respond_to?(:to_sym) ? key.to_sym : key
172
- new_hash.merge!(new_key => value)
173
- end
174
- end
175
161
  end
176
162
  end
177
163
  end
@@ -15,10 +15,3 @@ module Grape
15
15
  end
16
16
  end
17
17
  end
18
-
19
- # only exists to make it shorter for external use
20
- module Grape
21
- module Types
22
- InvalidValue = Class.new(Grape::Validations::Types::InvalidValue)
23
- end
24
- end
@@ -46,34 +46,23 @@ module Grape
46
46
  # there may be more than one error per field
47
47
  array_errors = []
48
48
 
49
- attributes.each do |val, attr_name, empty_val, skip_value|
50
- next if skip_value
49
+ attributes.each do |val, attr_name, empty_val|
51
50
  next if !@scope.required? && empty_val
52
51
  next unless @scope.meets_dependency?(val, params)
53
52
 
54
- begin
55
- validate_param!(attr_name, val) if @required || (val.respond_to?(:key?) && val.key?(attr_name))
56
- rescue Grape::Exceptions::Validation => e
57
- array_errors << e
58
- end
53
+ validate_param!(attr_name, val) if @required || (val.respond_to?(:key?) && val.key?(attr_name))
54
+ rescue Grape::Exceptions::Validation => e
55
+ array_errors << e
59
56
  end
60
57
 
61
58
  raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors.any?
62
59
  end
63
60
 
64
- def self.convert_to_short_name(klass)
65
- ret = klass.name.gsub(/::/, '/')
66
- ret.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
67
- ret.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
68
- ret.tr!('-', '_')
69
- ret.downcase!
70
- File.basename(ret, '_validator')
71
- end
72
-
73
61
  def self.inherited(klass)
74
- return unless klass.name.present?
62
+ return if klass.name.blank?
75
63
 
76
- Validations.register_validator(convert_to_short_name(klass), klass)
64
+ short_validator_name = klass.name.demodulize.underscore.delete_suffix('_validator')
65
+ Validations.register_validator(short_validator_name, klass)
77
66
  end
78
67
 
79
68
  def message(default_key = nil)
@@ -95,8 +84,8 @@ module Grape
95
84
  end
96
85
 
97
86
  Grape::Validations::Base = Class.new(Grape::Validations::Validators::Base) do
98
- def initialize(*)
87
+ def self.inherited(*)
88
+ ActiveSupport::Deprecation.warn 'Grape::Validations::Base is deprecated! Use Grape::Validations::Validators::Base instead.'
99
89
  super
100
- warn '[DEPRECATION] `Grape::Validations::Base` is deprecated. Use `Grape::Validations::Validators::Base` instead.'
101
90
  end
102
91
  end
@@ -12,10 +12,10 @@ module Grape
12
12
  def validate_param!(attr_name, params)
13
13
  params[attr_name] = if @default.is_a? Proc
14
14
  @default.call
15
- elsif @default.frozen? || !duplicatable?(@default)
15
+ elsif @default.frozen? || !@default.duplicable?
16
16
  @default
17
17
  else
18
- duplicate(@default)
18
+ @default.dup
19
19
  end
20
20
  end
21
21
 
@@ -27,24 +27,6 @@ module Grape
27
27
  validate_param!(attr_name, resource_params) if resource_params.is_a?(Hash) && resource_params[attr_name].nil?
28
28
  end
29
29
  end
30
-
31
- private
32
-
33
- # return true if we might be able to dup this object
34
- def duplicatable?(obj)
35
- !obj.nil? &&
36
- obj != true &&
37
- obj != false &&
38
- !obj.is_a?(Symbol) &&
39
- !obj.is_a?(Numeric)
40
- end
41
-
42
- # make a best effort to dup the object
43
- def duplicate(obj)
44
- obj.dup
45
- rescue TypeError
46
- obj
47
- end
48
30
  end
49
31
  end
50
32
  end
@@ -8,14 +8,10 @@ module Grape
8
8
  attributes = MultipleAttributesIterator.new(self, @scope, params)
9
9
  array_errors = []
10
10
 
11
- attributes.each do |resource_params, skip_value|
12
- next if skip_value
13
-
14
- begin
15
- validate_params!(resource_params)
16
- rescue Grape::Exceptions::Validation => e
17
- array_errors << e
18
- end
11
+ attributes.each do |resource_params|
12
+ validate_params!(resource_params)
13
+ rescue Grape::Exceptions::Validation => e
14
+ array_errors << e
19
15
  end
20
16
 
21
17
  raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors.any?
@@ -10,13 +10,11 @@ module Grape
10
10
  @values = options[:value]
11
11
  @proc = options[:proc]
12
12
 
13
- warn '[DEPRECATION] The values validator except option is deprecated. ' \
14
- 'Use the except validator instead.' if @excepts
13
+ ActiveSupport::Deprecation.warn('The values validator except option is deprecated. Use the except validator instead.') if @excepts
15
14
 
16
15
  raise ArgumentError, 'proc must be a Proc' if @proc && !@proc.is_a?(Proc)
17
16
 
18
- warn '[DEPRECATION] The values validator proc option is deprecated. ' \
19
- 'The lambda expression can now be assigned directly to values.' if @proc
17
+ ActiveSupport::Deprecation.warn('The values validator proc option is deprecated. The lambda expression can now be assigned directly to values.') if @proc
20
18
  else
21
19
  @excepts = nil
22
20
  @values = nil
@@ -45,7 +43,7 @@ module Grape
45
43
  unless check_values(param_array, attr_name)
46
44
 
47
45
  raise validation_exception(attr_name, message(:values)) \
48
- if @proc && !param_array.all? { |param| @proc.call(param) }
46
+ if @proc && !validate_proc(@proc, param_array)
49
47
  end
50
48
 
51
49
  private
@@ -70,6 +68,17 @@ module Grape
70
68
  param_array.none? { |param| excepts.include?(param) }
71
69
  end
72
70
 
71
+ def validate_proc(proc, param_array)
72
+ case proc.arity
73
+ when 0
74
+ param_array.all? { |_param| proc.call }
75
+ when 1
76
+ param_array.all? { |param| proc.call(param) }
77
+ else
78
+ raise ArgumentError, 'proc arity must be 0 or 1'
79
+ end
80
+ end
81
+
73
82
  def except_message
74
83
  options = instance_variable_get(:@option)
75
84
  options_key?(:except_message) ? options[:except_message] : message(:except_values)
data/lib/grape/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Grape
4
4
  # The current version of Grape.
5
- VERSION = '1.7.0'
5
+ VERSION = '1.8.0'
6
6
  end
data/lib/grape.rb CHANGED
@@ -11,6 +11,7 @@ require 'bigdecimal'
11
11
  require 'date'
12
12
  require 'active_support'
13
13
  require 'active_support/concern'
14
+ require 'active_support/configurable'
14
15
  require 'active_support/version'
15
16
  require 'active_support/isolated_execution_state' if ActiveSupport::VERSION::MAJOR > 6
16
17
  require 'active_support/core_ext/array/conversions'
@@ -20,16 +21,21 @@ require 'active_support/core_ext/hash/conversions'
20
21
  require 'active_support/core_ext/hash/deep_merge'
21
22
  require 'active_support/core_ext/hash/except'
22
23
  require 'active_support/core_ext/hash/indifferent_access'
24
+ require 'active_support/core_ext/hash/keys'
23
25
  require 'active_support/core_ext/hash/reverse_merge'
24
26
  require 'active_support/core_ext/hash/slice'
25
27
  require 'active_support/core_ext/object/blank'
28
+ require 'active_support/core_ext/object/duplicable'
26
29
  require 'active_support/dependencies/autoload'
30
+ require 'active_support/deprecation'
31
+ require 'active_support/inflector'
27
32
  require 'active_support/notifications'
28
33
  require 'i18n'
29
34
 
30
35
  I18n.load_path << File.expand_path('grape/locale/en.yml', __dir__)
31
36
 
32
37
  module Grape
38
+ include ActiveSupport::Configurable
33
39
  extend ::ActiveSupport::Autoload
34
40
 
35
41
  eager_autoload do
@@ -92,8 +98,6 @@ module Grape
92
98
  module Extensions
93
99
  extend ::ActiveSupport::Autoload
94
100
  eager_autoload do
95
- autoload :DeepMergeableHash
96
- autoload :DeepSymbolizeHash
97
101
  autoload :Hash
98
102
  end
99
103
  module ActiveSupport
@@ -277,9 +281,21 @@ module Grape
277
281
  end
278
282
  end
279
283
  end
284
+
285
+ module Types
286
+ extend ::ActiveSupport::Autoload
287
+
288
+ eager_autoload do
289
+ autoload :InvalidValue
290
+ end
291
+ end
292
+
293
+ configure do |config|
294
+ config.param_builder = Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
295
+ config.compile_methods!
296
+ end
280
297
  end
281
298
 
282
- require 'grape/config'
283
299
  require 'grape/content_types'
284
300
 
285
301
  require 'grape/util/lazy_value'