grape 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +120 -19
  5. data/UPGRADING.md +19 -4
  6. data/lib/grape/api/instance.rb +1 -1
  7. data/lib/grape/dsl/api.rb +0 -2
  8. data/lib/grape/dsl/callbacks.rb +0 -2
  9. data/lib/grape/dsl/configuration.rb +0 -2
  10. data/lib/grape/dsl/desc.rb +0 -15
  11. data/lib/grape/dsl/helpers.rb +0 -2
  12. data/lib/grape/dsl/inside_route.rb +33 -29
  13. data/lib/grape/dsl/middleware.rb +0 -2
  14. data/lib/grape/dsl/parameters.rb +5 -7
  15. data/lib/grape/dsl/request_response.rb +0 -2
  16. data/lib/grape/dsl/routing.rb +4 -2
  17. data/lib/grape/dsl/settings.rb +0 -2
  18. data/lib/grape/dsl/validations.rb +0 -15
  19. data/lib/grape/error_formatter/json.rb +7 -1
  20. data/lib/grape/exceptions/base.rb +2 -2
  21. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  22. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  23. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  24. data/lib/grape/exceptions/validation.rb +0 -4
  25. data/lib/grape/locale/en.yml +9 -8
  26. data/lib/grape/middleware/auth/dsl.rb +0 -1
  27. data/lib/grape/middleware/error.rb +2 -2
  28. data/lib/grape/request.rb +2 -0
  29. data/lib/grape/validations/attributes_doc.rb +58 -0
  30. data/lib/grape/validations/params_scope.rb +66 -40
  31. data/lib/grape/validations/types/array_coercer.rb +2 -2
  32. data/lib/grape/validations/types/build_coercer.rb +94 -0
  33. data/lib/grape/validations/types/dry_type_coercer.rb +13 -8
  34. data/lib/grape/validations/types/json.rb +2 -0
  35. data/lib/grape/validations/types/primitive_coercer.rb +20 -10
  36. data/lib/grape/validations/types/set_coercer.rb +3 -2
  37. data/lib/grape/validations/types.rb +20 -26
  38. data/lib/grape/validations/validators/base.rb +7 -0
  39. data/lib/grape/validations.rb +16 -6
  40. data/lib/grape/version.rb +1 -1
  41. data/lib/grape.rb +20 -15
  42. data/spec/grape/api/custom_validations_spec.rb +41 -2
  43. data/spec/grape/api/deeply_included_options_spec.rb +0 -2
  44. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -2
  45. data/spec/grape/api/documentation_spec.rb +59 -0
  46. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  47. data/spec/grape/api/instance_spec.rb +0 -1
  48. data/spec/grape/api/invalid_format_spec.rb +0 -2
  49. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  50. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  51. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  52. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  53. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  54. data/spec/grape/api/recognize_path_spec.rb +0 -2
  55. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  56. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  57. data/spec/grape/api/routes_with_requirements_spec.rb +0 -2
  58. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -2
  59. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  60. data/spec/grape/api_remount_spec.rb +0 -1
  61. data/spec/grape/api_spec.rb +18 -5
  62. data/spec/grape/config_spec.rb +0 -2
  63. data/spec/grape/dsl/callbacks_spec.rb +0 -2
  64. data/spec/grape/dsl/configuration_spec.rb +0 -2
  65. data/spec/grape/dsl/desc_spec.rb +0 -2
  66. data/spec/grape/dsl/headers_spec.rb +2 -4
  67. data/spec/grape/dsl/helpers_spec.rb +0 -2
  68. data/spec/grape/dsl/inside_route_spec.rb +10 -12
  69. data/spec/grape/dsl/logger_spec.rb +0 -2
  70. data/spec/grape/dsl/middleware_spec.rb +0 -2
  71. data/spec/grape/dsl/parameters_spec.rb +0 -2
  72. data/spec/grape/dsl/request_response_spec.rb +6 -8
  73. data/spec/grape/dsl/routing_spec.rb +1 -3
  74. data/spec/grape/dsl/settings_spec.rb +0 -2
  75. data/spec/grape/dsl/validations_spec.rb +0 -17
  76. data/spec/grape/endpoint/declared_spec.rb +2 -4
  77. data/spec/grape/endpoint_spec.rb +22 -3
  78. data/spec/grape/entity_spec.rb +0 -1
  79. data/spec/grape/exceptions/base_spec.rb +16 -2
  80. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -2
  81. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -2
  82. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  83. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  84. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  85. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  86. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  87. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  88. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  89. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  90. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  91. data/spec/grape/exceptions/validation_errors_spec.rb +0 -1
  92. data/spec/grape/exceptions/validation_spec.rb +1 -3
  93. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -2
  94. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -2
  95. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -2
  96. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  97. data/spec/grape/integration/rack_sendfile_spec.rb +0 -2
  98. data/spec/grape/integration/rack_spec.rb +0 -2
  99. data/spec/grape/loading_spec.rb +0 -2
  100. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  101. data/spec/grape/middleware/auth/dsl_spec.rb +0 -2
  102. data/spec/grape/middleware/auth/strategies_spec.rb +0 -2
  103. data/spec/grape/middleware/base_spec.rb +0 -2
  104. data/spec/grape/middleware/error_spec.rb +6 -1
  105. data/spec/grape/middleware/exception_spec.rb +0 -2
  106. data/spec/grape/middleware/formatter_spec.rb +0 -2
  107. data/spec/grape/middleware/globals_spec.rb +0 -2
  108. data/spec/grape/middleware/stack_spec.rb +0 -2
  109. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -2
  110. data/spec/grape/middleware/versioner/header_spec.rb +18 -4
  111. data/spec/grape/middleware/versioner/param_spec.rb +0 -2
  112. data/spec/grape/middleware/versioner/path_spec.rb +0 -2
  113. data/spec/grape/middleware/versioner_spec.rb +0 -2
  114. data/spec/grape/named_api_spec.rb +0 -2
  115. data/spec/grape/parser_spec.rb +0 -2
  116. data/spec/grape/path_spec.rb +0 -2
  117. data/spec/grape/presenters/presenter_spec.rb +0 -2
  118. data/spec/grape/request_spec.rb +0 -2
  119. data/spec/grape/util/inheritable_setting_spec.rb +0 -1
  120. data/spec/grape/util/inheritable_values_spec.rb +0 -1
  121. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -1
  122. data/spec/grape/util/stackable_values_spec.rb +0 -1
  123. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  124. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  125. data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
  126. data/spec/grape/validations/instance_behaivour_spec.rb +0 -2
  127. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -2
  128. data/spec/grape/validations/params_scope_spec.rb +315 -86
  129. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -2
  130. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  131. data/spec/grape/validations/types/primitive_coercer_spec.rb +20 -5
  132. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  133. data/spec/grape/validations/types_spec.rb +28 -2
  134. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -2
  135. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -2
  136. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -2
  137. data/spec/grape/validations/validators/coerce_spec.rb +0 -2
  138. data/spec/grape/validations/validators/default_spec.rb +0 -2
  139. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -2
  140. data/spec/grape/validations/validators/except_values_spec.rb +0 -2
  141. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -2
  142. data/spec/grape/validations/validators/presence_spec.rb +0 -2
  143. data/spec/grape/validations/validators/regexp_spec.rb +0 -2
  144. data/spec/grape/validations/validators/same_as_spec.rb +0 -2
  145. data/spec/grape/validations/validators/values_spec.rb +0 -2
  146. data/spec/grape/validations_spec.rb +50 -22
  147. data/spec/integration/multi_json/json_spec.rb +0 -2
  148. data/spec/integration/multi_xml/xml_spec.rb +0 -2
  149. data/spec/spec_helper.rb +9 -4
  150. metadata +17 -8
  151. data/spec/support/eager_load.rb +0 -19
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'grape/validations/types/json'
4
+ require 'grape/validations/types/file'
5
+
3
6
  module Grape
4
7
  module Validations
5
8
  # Module for code related to grape's system for
@@ -13,7 +16,8 @@ module Grape
13
16
  # and {Grape::Dsl::Parameters#optional}. The main
14
17
  # entry point for this process is {Types.build_coercer}.
15
18
  module Types
16
- # Types representing a single value, which are coerced.
19
+ module_function
20
+
17
21
  PRIMITIVES = [
18
22
  # Numerical
19
23
  Integer,
@@ -35,33 +39,23 @@ module Grape
35
39
  ].freeze
36
40
 
37
41
  # Types representing data structures.
38
- STRUCTURES = [
39
- Hash,
40
- Array,
41
- Set
42
- ].freeze
42
+ STRUCTURES = [Hash, Array, Set].freeze
43
43
 
44
- # Special custom types provided by Grape.
45
44
  SPECIAL = {
46
- JSON => Json,
45
+ ::JSON => Json,
47
46
  Array[JSON] => JsonArray,
48
47
  ::File => File,
49
48
  Rack::Multipart::UploadedFile => File
50
49
  }.freeze
51
50
 
52
- GROUPS = [
53
- Array,
54
- Hash,
55
- JSON,
56
- Array[JSON]
57
- ].freeze
51
+ GROUPS = [Array, Hash, JSON, Array[JSON]].freeze
58
52
 
59
53
  # Is the given class a primitive type as recognized by Grape?
60
54
  #
61
55
  # @param type [Class] type to check
62
56
  # @return [Boolean] whether or not the type is known by Grape as a valid
63
57
  # type for a single value
64
- def self.primitive?(type)
58
+ def primitive?(type)
65
59
  PRIMITIVES.include?(type)
66
60
  end
67
61
 
@@ -71,7 +65,7 @@ module Grape
71
65
  # @param type [Class] type to check
72
66
  # @return [Boolean] whether or not the type is known by Grape as a valid
73
67
  # data structure type
74
- def self.structure?(type)
68
+ def structure?(type)
75
69
  STRUCTURES.include?(type)
76
70
  end
77
71
 
@@ -83,7 +77,7 @@ module Grape
83
77
  # @param type [Array<Class>,Set<Class>] type (or type list!) to check
84
78
  # @return [Boolean] +true+ if the given value will be treated as
85
79
  # a list of types.
86
- def self.multiple?(type)
80
+ def multiple?(type)
87
81
  (type.is_a?(Array) || type.is_a?(Set)) && type.size > 1
88
82
  end
89
83
 
@@ -94,7 +88,7 @@ module Grape
94
88
  #
95
89
  # @param type [Class] type to check
96
90
  # @return [Boolean] +true+ if special routines are available
97
- def self.special?(type)
91
+ def special?(type)
98
92
  SPECIAL.key? type
99
93
  end
100
94
 
@@ -103,7 +97,7 @@ module Grape
103
97
  #
104
98
  # @param type [Array<Class>,Class] type to check
105
99
  # @return [Boolean] +true+ if the type is a supported group type
106
- def self.group?(type)
100
+ def group?(type)
107
101
  GROUPS.include? type
108
102
  end
109
103
 
@@ -112,7 +106,7 @@ module Grape
112
106
  #
113
107
  # @param type [Class] type to check
114
108
  # @return [Boolean] whether or not the type can be used as a custom type
115
- def self.custom?(type)
109
+ def custom?(type)
116
110
  !primitive?(type) &&
117
111
  !structure?(type) &&
118
112
  !multiple?(type) &&
@@ -125,13 +119,13 @@ module Grape
125
119
  # @param type [Array<Class>,Class] type to check
126
120
  # @return [Boolean] true if +type+ is a collection of a type that implements
127
121
  # its own +#parse+ method.
128
- def self.collection_of_custom?(type)
122
+ def collection_of_custom?(type)
129
123
  (type.is_a?(Array) || type.is_a?(Set)) &&
130
124
  type.length == 1 &&
131
125
  (custom?(type.first) || special?(type.first))
132
126
  end
133
127
 
134
- def self.map_special(type)
128
+ def map_special(type)
135
129
  SPECIAL.fetch(type, type)
136
130
  end
137
131
 
@@ -163,13 +157,13 @@ module Grape
163
157
  # @param method [Class,#call] the coercion method to use
164
158
  # @return [Object] object to be used
165
159
  # for coercion and type validation
166
- def self.build_coercer(type, method: nil, strict: false)
160
+ def build_coercer(type, method: nil, strict: false)
167
161
  cache_instance(type, method, strict) do
168
162
  create_coercer_instance(type, method, strict)
169
163
  end
170
164
  end
171
165
 
172
- def self.create_coercer_instance(type, method, strict)
166
+ def create_coercer_instance(type, method, strict)
173
167
  # Maps a custom type provided by Grape, it doesn't map types wrapped by collections!!!
174
168
  type = Types.map_special(type)
175
169
 
@@ -193,7 +187,7 @@ module Grape
193
187
  end
194
188
  end
195
189
 
196
- def self.cache_instance(type, method, strict, &_block)
190
+ def cache_instance(type, method, strict, &_block)
197
191
  key = cache_key(type, method, strict)
198
192
 
199
193
  return @__cache[key] if @__cache.key?(key)
@@ -207,7 +201,7 @@ module Grape
207
201
  instance
208
202
  end
209
203
 
210
- def self.cache_key(type, method, strict)
204
+ def cache_key(type, method, strict)
211
205
  [type, method, strict].each_with_object(+'_') do |val, memo|
212
206
  next if val.nil?
213
207
 
@@ -93,3 +93,10 @@ module Grape
93
93
  end
94
94
  end
95
95
  end
96
+
97
+ Grape::Validations::Base = Class.new(Grape::Validations::Validators::Base) do
98
+ def initialize(*)
99
+ super
100
+ warn '[DEPRECATION] `Grape::Validations::Base` is deprecated. Use `Grape::Validations::Validators::Base` instead.'
101
+ end
102
+ end
@@ -3,22 +3,32 @@
3
3
  module Grape
4
4
  # Registry to store and locate known Validators.
5
5
  module Validations
6
- class << self
7
- attr_accessor :validators
8
- end
6
+ module_function
9
7
 
10
- self.validators = {}
8
+ def validators
9
+ @validators ||= {}
10
+ end
11
11
 
12
12
  # Register a new validator, so it can be used to validate parameters.
13
13
  # @param short_name [String] all lower-case, no spaces
14
14
  # @param klass [Class] the validator class. Should inherit from
15
15
  # Validations::Base.
16
- def self.register_validator(short_name, klass)
16
+ def register_validator(short_name, klass)
17
17
  validators[short_name] = klass
18
18
  end
19
19
 
20
- def self.deregister_validator(short_name)
20
+ def deregister_validator(short_name)
21
21
  validators.delete(short_name)
22
22
  end
23
+
24
+ # Find a validator and if not found will try to load it
25
+ def require_validator(short_name)
26
+ str_name = short_name.to_s
27
+ validators.fetch(str_name) do
28
+ Grape::Validations::Validators.const_get("#{str_name.camelize}Validator")
29
+ end
30
+ rescue NameError
31
+ raise Grape::Exceptions::UnknownValidator.new(short_name)
32
+ end
23
33
  end
24
34
  end
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.6.1'
5
+ VERSION = '1.7.0'
6
6
  end
data/lib/grape.rb CHANGED
@@ -7,19 +7,22 @@ require 'rack/accept'
7
7
  require 'rack/auth/basic'
8
8
  require 'rack/auth/digest/md5'
9
9
  require 'set'
10
+ require 'bigdecimal'
11
+ require 'date'
10
12
  require 'active_support'
13
+ require 'active_support/concern'
11
14
  require 'active_support/version'
12
15
  require 'active_support/isolated_execution_state' if ActiveSupport::VERSION::MAJOR > 6
13
- require 'active_support/core_ext/hash/indifferent_access'
14
- require 'active_support/core_ext/object/blank'
15
16
  require 'active_support/core_ext/array/conversions'
16
17
  require 'active_support/core_ext/array/extract_options'
17
18
  require 'active_support/core_ext/array/wrap'
18
19
  require 'active_support/core_ext/hash/conversions'
19
20
  require 'active_support/core_ext/hash/deep_merge'
20
21
  require 'active_support/core_ext/hash/except'
22
+ require 'active_support/core_ext/hash/indifferent_access'
21
23
  require 'active_support/core_ext/hash/reverse_merge'
22
24
  require 'active_support/core_ext/hash/slice'
25
+ require 'active_support/core_ext/object/blank'
23
26
  require 'active_support/dependencies/autoload'
24
27
  require 'active_support/notifications'
25
28
  require 'i18n'
@@ -72,14 +75,17 @@ module Grape
72
75
  autoload :UnknownParameter
73
76
  autoload :InvalidWithOptionForRepresent
74
77
  autoload :IncompatibleOptionValues
75
- autoload :MissingGroupTypeError, 'grape/exceptions/missing_group_type'
76
- autoload :UnsupportedGroupTypeError, 'grape/exceptions/unsupported_group_type'
78
+ autoload :MissingGroupType
79
+ autoload :UnsupportedGroupType
77
80
  autoload :InvalidMessageBody
78
81
  autoload :InvalidAcceptHeader
79
82
  autoload :InvalidVersionHeader
80
83
  autoload :MethodNotAllowed
81
84
  autoload :InvalidResponse
82
85
  autoload :EmptyMessageBody
86
+ autoload :TooManyMultipartFiles
87
+ autoload :MissingGroupTypeError, 'grape/exceptions/missing_group_type'
88
+ autoload :UnsupportedGroupTypeError, 'grape/exceptions/unsupported_group_type'
83
89
  end
84
90
  end
85
91
 
@@ -223,13 +229,21 @@ module Grape
223
229
  module Validations
224
230
  extend ::ActiveSupport::Autoload
225
231
 
232
+ eager_autoload do
233
+ autoload :AttributesIterator
234
+ autoload :MultipleAttributesIterator
235
+ autoload :SingleAttributeIterator
236
+ autoload :Types
237
+ autoload :ParamsScope
238
+ autoload :ValidatorFactory
239
+ autoload :Base, 'grape/validations/validators/base'
240
+ end
241
+
226
242
  module Types
227
243
  extend ::ActiveSupport::Autoload
228
244
 
229
245
  eager_autoload do
230
246
  autoload :InvalidValue
231
- autoload :File
232
- autoload :Json
233
247
  autoload :DryTypeCoercer
234
248
  autoload :ArrayCoercer
235
249
  autoload :SetCoercer
@@ -241,15 +255,6 @@ module Grape
241
255
  end
242
256
  end
243
257
 
244
- eager_autoload do
245
- autoload :AttributesIterator
246
- autoload :MultipleAttributesIterator
247
- autoload :SingleAttributeIterator
248
- autoload :ParamsScope
249
- autoload :Types
250
- autoload :ValidatorFactory
251
- end
252
-
253
258
  module Validators
254
259
  extend ::ActiveSupport::Autoload
255
260
 
@@ -1,8 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations do
4
+ context 'deprecated Grape::Validations::Base' do
5
+ subject do
6
+ Class.new(Grape::API) do
7
+ params do
8
+ requires :text, validator_with_old_base: true
9
+ end
10
+ get do
11
+ end
12
+ end
13
+ end
14
+
15
+ let(:validator_with_old_base) do
16
+ Class.new(Grape::Validations::Base) do
17
+ def validate_param!(_attr_name, _params)
18
+ true
19
+ end
20
+ end
21
+ end
22
+
23
+ before do
24
+ described_class.register_validator('validator_with_old_base', validator_with_old_base)
25
+ allow(Warning).to receive(:warn)
26
+ end
27
+
28
+ after do
29
+ described_class.deregister_validator('validator_with_old_base')
30
+ end
31
+
32
+ def app
33
+ subject
34
+ end
35
+
36
+ it 'puts a deprecation warning' do
37
+ expect(Warning).to receive(:warn) do |message|
38
+ expect(message).to include('`Grape::Validations::Base` is deprecated')
39
+ end
40
+
41
+ get '/'
42
+ end
43
+ end
44
+
6
45
  context 'using a custom length validator' do
7
46
  subject do
8
47
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module DeeplyIncludedOptionsSpec
6
4
  module Defaults
7
5
  extend ActiveSupport::Concern
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API::Instance do
6
4
  describe 'boolean constant' do
7
5
  module DefinesBooleanInstanceSpec
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::API do
6
+ subject { Class.new(described_class) }
7
+
8
+ let(:app) { subject }
9
+
10
+ context 'an endpoint with documentation' do
11
+ it 'documents parameters' do
12
+ subject.params do
13
+ requires 'price', type: Float, desc: 'Sales price'
14
+ end
15
+ subject.get '/'
16
+
17
+ expect(subject.routes.first.params['price']).to eq(required: true,
18
+ type: 'Float',
19
+ desc: 'Sales price')
20
+ end
21
+
22
+ it 'allows documentation with a hash' do
23
+ documentation = { example: 'Joe' }
24
+
25
+ subject.params do
26
+ requires 'first_name', documentation: documentation
27
+ end
28
+ subject.get '/'
29
+
30
+ expect(subject.routes.first.params['first_name'][:documentation]).to eq(documentation)
31
+ end
32
+ end
33
+
34
+ context 'an endpoint without documentation' do
35
+ before do
36
+ subject.do_not_document!
37
+
38
+ subject.params do
39
+ requires :city, type: String, desc: 'Should be ignored'
40
+ optional :postal_code, type: Integer
41
+ end
42
+ subject.post '/' do
43
+ declared(params).to_json
44
+ end
45
+ end
46
+
47
+ it 'does not document parameters for the endpoint' do
48
+ expect(subject.routes.first.params).to eq({})
49
+ end
50
+
51
+ it 'still declares params internally' do
52
+ data = { city: 'Berlin', postal_code: 10_115 }
53
+
54
+ post '/', data
55
+
56
+ expect(last_response.body).to eq(data.to_json)
57
+ end
58
+ end
59
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API::Helpers do
6
4
  let(:user) { 'Miguel Caneo' }
7
5
  let(:id) { '42' }
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  require 'shared/versioning_examples'
5
4
 
6
5
  describe Grape::API::Instance do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API::Helpers do
6
4
  module NestedHelpersSpec
7
5
  module HelperMethods
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API::Helpers do
6
4
  module PatchHelpersSpec
7
5
  class PatchPublic < Grape::API
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API do
6
4
  describe '.recognize_path' do
7
5
  subject { Class.new(described_class) }
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API::Helpers do
6
4
  let(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::API::Helpers do
6
4
  subject do
7
5
  shared_params = Module.new do
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  require 'shared/versioning_examples'
5
4
 
6
5
  describe Grape::API do
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  require 'shared/versioning_examples'
5
4
 
6
5
  describe Grape::API do
@@ -1217,7 +1216,7 @@ describe Grape::API do
1217
1216
 
1218
1217
  it 'does not set Cache-Control' do
1219
1218
  get '/foo'
1220
- expect(last_response.headers['Cache-Control']).to eq(nil)
1219
+ expect(last_response.headers['Cache-Control']).to be_nil
1221
1220
  end
1222
1221
 
1223
1222
  it 'sets content type for xml' do
@@ -1242,7 +1241,7 @@ describe Grape::API do
1242
1241
 
1243
1242
  it 'returns raw data when content type binary' do
1244
1243
  image_filename = 'grape.png'
1245
- file = File.open(image_filename, 'rb', &:read)
1244
+ file = File.binread(image_filename)
1246
1245
  subject.format :binary
1247
1246
  subject.get('/binary_file') { File.binread(image_filename) }
1248
1247
  get '/binary_file'
@@ -1274,7 +1273,7 @@ describe Grape::API do
1274
1273
  get '/stream', {}, 'HTTP_VERSION' => 'HTTP/1.1', 'SERVER_PROTOCOL' => 'HTTP/1.1'
1275
1274
 
1276
1275
  expect(last_response.headers['Content-Type']).to eq('text/plain')
1277
- expect(last_response.headers['Content-Length']).to eq(nil)
1276
+ expect(last_response.headers['Content-Length']).to be_nil
1278
1277
  expect(last_response.headers['Cache-Control']).to eq('no-cache')
1279
1278
  expect(last_response.headers['Transfer-Encoding']).to eq('chunked')
1280
1279
 
@@ -2292,7 +2291,7 @@ describe Grape::API do
2292
2291
  subject.rescue_from :all, with: :not_exist_method
2293
2292
  subject.get('/rescue_method') { raise StandardError }
2294
2293
 
2295
- expect { get '/rescue_method' }.to raise_error(NoMethodError, /^undefined method `not_exist_method'/)
2294
+ expect { get '/rescue_method' }.to raise_error(NoMethodError, /^undefined method 'not_exist_method'/)
2296
2295
  end
2297
2296
 
2298
2297
  it 'correctly chooses exception handler if :all handler is specified' do
@@ -4158,6 +4157,20 @@ describe Grape::API do
4158
4157
  end
4159
4158
  end
4160
4159
 
4160
+ context 'with non-UTF-8 characters in specified format' do
4161
+ it 'converts the characters' do
4162
+ subject.format :json
4163
+ subject.content_type :json, 'application/json'
4164
+ subject.get '/something' do
4165
+ 'foo'
4166
+ end
4167
+ get '/something?format=%0A%0B%BF'
4168
+ expect(last_response.status).to eq(406)
4169
+ message = "The requested format '\n\u000b\357\277\275' is not supported."
4170
+ expect(last_response.body).to eq({ error: message }.to_json)
4171
+ end
4172
+ end
4173
+
4161
4174
  context 'body' do
4162
4175
  context 'false' do
4163
4176
  before do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe '.configure' do
6
4
  before do
7
5
  Grape.configure do |config|
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module CallbacksSpec
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module ConfigurationSpec
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module DescSpec
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module HeadersSpec
@@ -54,8 +52,8 @@ module Grape
54
52
  context 'when no headers are set' do
55
53
  describe '#header' do
56
54
  it 'returns nil' do
57
- expect(subject.header['First Key']).to be nil
58
- expect(subject.header('First Key')).to be nil
55
+ expect(subject.header['First Key']).to be_nil
56
+ expect(subject.header('First Key')).to be_nil
59
57
  end
60
58
  end
61
59
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module HelpersSpec