grape 1.5.3 → 1.7.1

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.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/CONTRIBUTING.md +32 -1
  4. data/README.md +176 -25
  5. data/UPGRADING.md +61 -4
  6. data/grape.gemspec +6 -6
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +17 -12
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dry_types.rb +12 -0
  11. data/lib/grape/dsl/api.rb +0 -2
  12. data/lib/grape/dsl/callbacks.rb +0 -2
  13. data/lib/grape/dsl/configuration.rb +0 -2
  14. data/lib/grape/dsl/desc.rb +4 -20
  15. data/lib/grape/dsl/headers.rb +5 -2
  16. data/lib/grape/dsl/helpers.rb +7 -7
  17. data/lib/grape/dsl/inside_route.rb +43 -30
  18. data/lib/grape/dsl/middleware.rb +4 -6
  19. data/lib/grape/dsl/parameters.rb +13 -10
  20. data/lib/grape/dsl/request_response.rb +9 -8
  21. data/lib/grape/dsl/routing.rb +6 -4
  22. data/lib/grape/dsl/settings.rb +5 -7
  23. data/lib/grape/dsl/validations.rb +0 -15
  24. data/lib/grape/endpoint.rb +22 -37
  25. data/lib/grape/error_formatter/json.rb +9 -7
  26. data/lib/grape/error_formatter/xml.rb +2 -6
  27. data/lib/grape/exceptions/base.rb +3 -2
  28. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  29. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  30. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  31. data/lib/grape/exceptions/validation.rb +1 -6
  32. data/lib/grape/formatter/json.rb +1 -0
  33. data/lib/grape/formatter/serializable_hash.rb +2 -1
  34. data/lib/grape/formatter/xml.rb +1 -0
  35. data/lib/grape/locale/en.yml +9 -8
  36. data/lib/grape/middleware/auth/dsl.rb +7 -2
  37. data/lib/grape/middleware/base.rb +3 -1
  38. data/lib/grape/middleware/error.rb +2 -2
  39. data/lib/grape/middleware/formatter.rb +4 -4
  40. data/lib/grape/middleware/stack.rb +3 -3
  41. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  42. data/lib/grape/middleware/versioner/header.rb +6 -4
  43. data/lib/grape/middleware/versioner/param.rb +1 -0
  44. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  45. data/lib/grape/middleware/versioner/path.rb +2 -0
  46. data/lib/grape/path.rb +1 -0
  47. data/lib/grape/request.rb +4 -1
  48. data/lib/grape/router/attribute_translator.rb +1 -1
  49. data/lib/grape/router/pattern.rb +1 -1
  50. data/lib/grape/router/route.rb +2 -2
  51. data/lib/grape/router.rb +6 -0
  52. data/lib/grape/types/invalid_value.rb +8 -0
  53. data/lib/grape/util/cache.rb +1 -1
  54. data/lib/grape/util/inheritable_setting.rb +1 -3
  55. data/lib/grape/util/json.rb +2 -0
  56. data/lib/grape/util/lazy_value.rb +3 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_doc.rb +58 -0
  59. data/lib/grape/validations/params_scope.rb +138 -79
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/invalid_value.rb +0 -7
  64. data/lib/grape/validations/types/json.rb +2 -1
  65. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  66. data/lib/grape/validations/types/set_coercer.rb +0 -2
  67. data/lib/grape/validations/types.rb +98 -30
  68. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  69. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  70. data/lib/grape/validations/validators/as_validator.rb +14 -0
  71. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  72. data/lib/grape/validations/validators/base.rb +82 -70
  73. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  74. data/lib/grape/validations/validators/default_validator.rb +51 -0
  75. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  76. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  77. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  78. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  79. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  80. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  81. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  82. data/lib/grape/validations/validators/values_validator.rb +88 -0
  83. data/lib/grape/validations.rb +16 -6
  84. data/lib/grape/version.rb +1 -1
  85. data/lib/grape.rb +77 -29
  86. data/spec/grape/api/custom_validations_spec.rb +116 -45
  87. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  88. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  89. data/spec/grape/api/documentation_spec.rb +59 -0
  90. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  91. data/spec/grape/api/instance_spec.rb +0 -1
  92. data/spec/grape/api/invalid_format_spec.rb +2 -2
  93. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  94. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  95. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  96. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  97. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  98. data/spec/grape/api/recognize_path_spec.rb +1 -3
  99. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  100. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  101. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  102. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  103. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  104. data/spec/grape/api_remount_spec.rb +16 -16
  105. data/spec/grape/api_spec.rb +462 -251
  106. data/spec/grape/config_spec.rb +0 -2
  107. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  108. data/spec/grape/dsl/desc_spec.rb +2 -2
  109. data/spec/grape/dsl/headers_spec.rb +39 -11
  110. data/spec/grape/dsl/helpers_spec.rb +3 -4
  111. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  112. data/spec/grape/dsl/logger_spec.rb +15 -19
  113. data/spec/grape/dsl/middleware_spec.rb +2 -3
  114. data/spec/grape/dsl/parameters_spec.rb +2 -2
  115. data/spec/grape/dsl/request_response_spec.rb +7 -8
  116. data/spec/grape/dsl/routing_spec.rb +11 -10
  117. data/spec/grape/dsl/settings_spec.rb +0 -2
  118. data/spec/grape/dsl/validations_spec.rb +0 -17
  119. data/spec/grape/endpoint/declared_spec.rb +261 -16
  120. data/spec/grape/endpoint_spec.rb +88 -59
  121. data/spec/grape/entity_spec.rb +22 -23
  122. data/spec/grape/exceptions/base_spec.rb +16 -2
  123. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  124. data/spec/grape/exceptions/invalid_accept_header_spec.rb +64 -24
  125. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  126. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  127. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  129. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  130. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  131. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  132. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  133. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  134. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  135. data/spec/grape/exceptions/validation_spec.rb +5 -5
  136. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  137. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  138. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  139. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  140. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  141. data/spec/grape/integration/rack_spec.rb +6 -7
  142. data/spec/grape/loading_spec.rb +8 -10
  143. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  144. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  145. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  146. data/spec/grape/middleware/base_spec.rb +28 -19
  147. data/spec/grape/middleware/error_spec.rb +8 -3
  148. data/spec/grape/middleware/exception_spec.rb +111 -163
  149. data/spec/grape/middleware/formatter_spec.rb +33 -14
  150. data/spec/grape/middleware/globals_spec.rb +7 -6
  151. data/spec/grape/middleware/stack_spec.rb +14 -14
  152. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  153. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  154. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  155. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  156. data/spec/grape/middleware/versioner_spec.rb +1 -3
  157. data/spec/grape/named_api_spec.rb +0 -2
  158. data/spec/grape/parser_spec.rb +4 -2
  159. data/spec/grape/path_spec.rb +52 -54
  160. data/spec/grape/presenters/presenter_spec.rb +7 -8
  161. data/spec/grape/request_spec.rb +6 -6
  162. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  163. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  164. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  165. data/spec/grape/util/stackable_values_spec.rb +7 -6
  166. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  167. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  168. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  169. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  170. data/spec/grape/validations/params_scope_spec.rb +361 -96
  171. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  172. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  173. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  174. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  175. data/spec/grape/validations/types_spec.rb +36 -10
  176. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  177. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  178. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  179. data/spec/grape/validations/validators/coerce_spec.rb +23 -24
  180. data/spec/grape/validations/validators/default_spec.rb +72 -80
  181. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  182. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  183. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  184. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  185. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  186. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  187. data/spec/grape/validations/validators/values_spec.rb +201 -179
  188. data/spec/grape/validations_spec.rb +171 -79
  189. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  190. data/spec/integration/multi_json/json_spec.rb +1 -3
  191. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  192. data/spec/shared/versioning_examples.rb +12 -9
  193. data/spec/spec_helper.rb +21 -6
  194. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  195. metadata +41 -29
  196. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  197. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  198. data/lib/grape/validations/validators/as.rb +0 -16
  199. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  200. data/lib/grape/validations/validators/coerce.rb +0 -91
  201. data/lib/grape/validations/validators/default.rb +0 -48
  202. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  203. data/lib/grape/validations/validators/except_values.rb +0 -22
  204. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  205. data/lib/grape/validations/validators/presence.rb +0 -12
  206. data/lib/grape/validations/validators/regexp.rb +0 -13
  207. data/lib/grape/validations/validators/same_as.rb +0 -26
  208. data/lib/grape/validations/validators/values.rb +0 -83
  209. data/spec/grape/dsl/configuration_spec.rb +0 -16
  210. data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
  211. data/spec/support/eager_load.rb +0 -19
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ describe Grape::Validations::Validators::ValuesValidator do
4
+ let_it_be(:values_model) do
5
+ Class.new do
6
+ DEFAULT_VALUES = %w[valid-type1 valid-type2 valid-type3].freeze
7
+ DEFAULT_EXCEPTS = %w[invalid-type1 invalid-type2 invalid-type3].freeze
4
8
 
5
- describe Grape::Validations::ValuesValidator do
6
- module ValidationsSpec
7
- class ValuesModel
8
- DEFAULT_VALUES = ['valid-type1', 'valid-type2', 'valid-type3'].freeze
9
- DEFAULT_EXCEPTS = ['invalid-type1', 'invalid-type2', 'invalid-type3'].freeze
10
9
  class << self
11
10
  def values
12
11
  @values ||= []
@@ -27,214 +26,226 @@ describe Grape::Validations::ValuesValidator do
27
26
  @excepts ||= []
28
27
  @excepts << except
29
28
  end
29
+
30
+ def include?(value)
31
+ values.include?(value)
32
+ end
30
33
  end
31
34
  end
35
+ end
32
36
 
33
- module ValuesValidatorSpec
34
- class API < Grape::API
35
- default_format :json
36
-
37
- resources :custom_message do
38
- params do
39
- requires :type, values: { value: ValuesModel.values, message: 'value does not include in values' }
40
- end
41
- get '/' do
42
- { type: params[:type] }
43
- end
44
-
45
- params do
46
- optional :type, values: { value: -> { ValuesModel.values }, message: 'value does not include in values' }, default: 'valid-type2'
47
- end
48
- get '/lambda' do
49
- { type: params[:type] }
50
- end
51
-
52
- params do
53
- requires :type, values: { except: ValuesModel.excepts, except_message: 'value is on exclusions list', message: 'default exclude message' }
54
- end
55
- get '/exclude/exclude_message'
56
-
57
- params do
58
- requires :type, values: { except: -> { ValuesModel.excepts }, except_message: 'value is on exclusions list' }
59
- end
60
- get '/exclude/lambda/exclude_message'
61
-
62
- params do
63
- requires :type, values: { except: ValuesModel.excepts, message: 'default exclude message' }
64
- end
65
- get '/exclude/fallback_message'
66
- end
37
+ before do
38
+ stub_const('ValuesModel', values_model)
39
+ end
67
40
 
41
+ let_it_be(:app) do
42
+ ValuesModel = values_model
43
+ Class.new(Grape::API) do
44
+ default_format :json
45
+
46
+ resources :custom_message do
68
47
  params do
69
- requires :type, values: ValuesModel.values
48
+ requires :type, values: { value: ValuesModel.values, message: 'value does not include in values' }
70
49
  end
71
50
  get '/' do
72
51
  { type: params[:type] }
73
52
  end
74
53
 
75
54
  params do
76
- requires :type, values: []
55
+ optional :type, values: { value: -> { ValuesModel.values }, message: 'value does not include in values' }, default: 'valid-type2'
77
56
  end
78
- get '/empty'
79
-
80
- params do
81
- optional :type, values: { value: ValuesModel.values }, default: 'valid-type2'
82
- end
83
- get '/default/hash/valid' do
57
+ get '/lambda' do
84
58
  { type: params[:type] }
85
59
  end
86
60
 
87
61
  params do
88
- optional :type, values: ValuesModel.values, default: 'valid-type2'
89
- end
90
- get '/default/valid' do
91
- { type: params[:type] }
62
+ requires :type, values: { except: ValuesModel.excepts, except_message: 'value is on exclusions list', message: 'default exclude message' }
92
63
  end
64
+ get '/exclude/exclude_message'
93
65
 
94
66
  params do
95
- optional :type, values: { except: ValuesModel.excepts }, default: 'valid-type2'
96
- end
97
- get '/default/except' do
98
- { type: params[:type] }
67
+ requires :type, values: { except: -> { ValuesModel.excepts }, except_message: 'value is on exclusions list' }
99
68
  end
69
+ get '/exclude/lambda/exclude_message'
100
70
 
101
71
  params do
102
- optional :type, values: -> { ValuesModel.values }, default: 'valid-type2'
103
- end
104
- get '/lambda' do
105
- { type: params[:type] }
72
+ requires :type, values: { except: ValuesModel.excepts, message: 'default exclude message' }
106
73
  end
74
+ get '/exclude/fallback_message'
75
+ end
107
76
 
108
- params do
109
- requires :type, values: ->(v) { ValuesModel.values.include? v }
110
- end
111
- get '/lambda_val' do
112
- { type: params[:type] }
113
- end
77
+ params do
78
+ requires :type, values: ValuesModel.values
79
+ end
80
+ get '/' do
81
+ { type: params[:type] }
82
+ end
114
83
 
115
- params do
116
- requires :number, type: Integer, values: ->(v) { v > 0 }
117
- end
118
- get '/lambda_int_val' do
119
- { number: params[:number] }
120
- end
84
+ params do
85
+ requires :type, values: []
86
+ end
87
+ get '/empty'
121
88
 
122
- params do
123
- requires :type, values: -> { [] }
124
- end
125
- get '/empty_lambda'
89
+ params do
90
+ optional :type, values: { value: ValuesModel.values }, default: 'valid-type2'
91
+ end
92
+ get '/default/hash/valid' do
93
+ { type: params[:type] }
94
+ end
126
95
 
127
- params do
128
- optional :type, values: ValuesModel.values, default: -> { ValuesModel.values.sample }
129
- end
130
- get '/default_lambda' do
131
- { type: params[:type] }
132
- end
96
+ params do
97
+ optional :type, values: ValuesModel.values, default: 'valid-type2'
98
+ end
99
+ get '/default/valid' do
100
+ { type: params[:type] }
101
+ end
133
102
 
134
- params do
135
- optional :type, values: -> { ValuesModel.values }, default: -> { ValuesModel.values.sample }
136
- end
137
- get '/default_and_values_lambda' do
138
- { type: params[:type] }
139
- end
103
+ params do
104
+ optional :type, values: { except: ValuesModel.excepts }, default: 'valid-type2'
105
+ end
106
+ get '/default/except' do
107
+ { type: params[:type] }
108
+ end
140
109
 
141
- params do
142
- optional :type, type: Boolean, desc: 'A boolean', values: [true]
143
- end
144
- get '/values/optional_boolean' do
145
- { type: params[:type] }
146
- end
110
+ params do
111
+ optional :type, values: -> { ValuesModel.values }, default: 'valid-type2'
112
+ end
113
+ get '/lambda' do
114
+ { type: params[:type] }
115
+ end
147
116
 
148
- params do
149
- requires :type, type: Integer, desc: 'An integer', values: [10, 11], default: 10
150
- end
151
- get '/values/coercion' do
152
- { type: params[:type] }
153
- end
117
+ params do
118
+ optional :type, type: Integer, values: 1..
119
+ end
120
+ get '/endless' do
121
+ { type: params[:type] }
122
+ end
154
123
 
155
- params do
156
- requires :type, type: Array[Integer], desc: 'An integer', values: [10, 11], default: 10
157
- end
158
- get '/values/array_coercion' do
159
- { type: params[:type] }
160
- end
124
+ params do
125
+ requires :type, values: ->(v) { ValuesModel.include? v }
126
+ end
127
+ get '/lambda_val' do
128
+ { type: params[:type] }
129
+ end
161
130
 
162
- params do
163
- optional :optional, type: Array do
164
- requires :type, values: %w[a b]
165
- end
166
- end
167
- get '/optional_with_required_values'
131
+ params do
132
+ requires :number, type: Integer, values: ->(v) { v > 0 }
133
+ end
134
+ get '/lambda_int_val' do
135
+ { number: params[:number] }
136
+ end
168
137
 
169
- params do
170
- requires :type, values: { except: ValuesModel.excepts }
171
- end
172
- get '/except/exclusive' do
173
- { type: params[:type] }
174
- end
138
+ params do
139
+ requires :type, values: -> { [] }
140
+ end
141
+ get '/empty_lambda'
175
142
 
176
- params do
177
- requires :type, type: String, values: { except: ValuesModel.excepts }
178
- end
179
- get '/except/exclusive/type' do
180
- { type: params[:type] }
181
- end
143
+ params do
144
+ optional :type, values: ValuesModel.values, default: -> { ValuesModel.values.sample }
145
+ end
146
+ get '/default_lambda' do
147
+ { type: params[:type] }
148
+ end
182
149
 
183
- params do
184
- requires :type, values: { except: -> { ValuesModel.excepts } }
185
- end
186
- get '/except/exclusive/lambda' do
187
- { type: params[:type] }
188
- end
150
+ params do
151
+ optional :type, values: -> { ValuesModel.values }, default: -> { ValuesModel.values.sample }
152
+ end
153
+ get '/default_and_values_lambda' do
154
+ { type: params[:type] }
155
+ end
189
156
 
190
- params do
191
- requires :type, type: String, values: { except: -> { ValuesModel.excepts } }
192
- end
193
- get '/except/exclusive/lambda/type' do
194
- { type: params[:type] }
195
- end
157
+ params do
158
+ optional :type, type: Grape::API::Boolean, desc: 'A boolean', values: [true]
159
+ end
160
+ get '/values/optional_boolean' do
161
+ { type: params[:type] }
162
+ end
196
163
 
197
- params do
198
- requires :type, type: Integer, values: { except: -> { [3, 4, 5] } }
199
- end
200
- get '/except/exclusive/lambda/coercion' do
201
- { type: params[:type] }
202
- end
164
+ params do
165
+ requires :type, type: Integer, desc: 'An integer', values: [10, 11], default: 10
166
+ end
167
+ get '/values/coercion' do
168
+ { type: params[:type] }
169
+ end
203
170
 
204
- params do
205
- requires :type, type: Integer, values: { value: 1..5, except: [3] }
206
- end
207
- get '/mixed/value/except' do
208
- { type: params[:type] }
209
- end
171
+ params do
172
+ requires :type, type: Array[Integer], desc: 'An integer', values: [10, 11], default: 10
173
+ end
174
+ get '/values/array_coercion' do
175
+ { type: params[:type] }
176
+ end
210
177
 
211
- params do
212
- optional :optional, type: Array[String], values: %w[a b c]
178
+ params do
179
+ optional :optional, type: Array do
180
+ requires :type, values: %w[a b]
213
181
  end
214
- put '/optional_with_array_of_string_values'
182
+ end
183
+ get '/optional_with_required_values'
215
184
 
216
- params do
217
- requires :type, values: { proc: ->(v) { ValuesModel.values.include? v } }
218
- end
219
- get '/proc' do
220
- { type: params[:type] }
221
- end
185
+ params do
186
+ requires :type, values: { except: ValuesModel.excepts }
187
+ end
188
+ get '/except/exclusive' do
189
+ { type: params[:type] }
190
+ end
222
191
 
223
- params do
224
- requires :type, values: { proc: ->(v) { ValuesModel.values.include? v }, message: 'failed check' }
225
- end
226
- get '/proc/message'
192
+ params do
193
+ requires :type, type: String, values: { except: ValuesModel.excepts }
194
+ end
195
+ get '/except/exclusive/type' do
196
+ { type: params[:type] }
197
+ end
227
198
 
228
- params do
229
- optional :name, type: String, values: %w[a b], allow_blank: true
230
- end
231
- get '/allow_blank'
199
+ params do
200
+ requires :type, values: { except: -> { ValuesModel.excepts } }
201
+ end
202
+ get '/except/exclusive/lambda' do
203
+ { type: params[:type] }
204
+ end
205
+
206
+ params do
207
+ requires :type, type: String, values: { except: -> { ValuesModel.excepts } }
208
+ end
209
+ get '/except/exclusive/lambda/type' do
210
+ { type: params[:type] }
211
+ end
212
+
213
+ params do
214
+ requires :type, type: Integer, values: { except: -> { [3, 4, 5] } }
215
+ end
216
+ get '/except/exclusive/lambda/coercion' do
217
+ { type: params[:type] }
218
+ end
219
+
220
+ params do
221
+ requires :type, type: Integer, values: { value: 1..5, except: [3] }
222
+ end
223
+ get '/mixed/value/except' do
224
+ { type: params[:type] }
232
225
  end
233
- end
234
- end
235
226
 
236
- def app
237
- ValidationsSpec::ValuesValidatorSpec::API
227
+ params do
228
+ optional :optional, type: Array[String], values: %w[a b c]
229
+ end
230
+ put '/optional_with_array_of_string_values'
231
+
232
+ params do
233
+ requires :type, values: { proc: ->(v) { ValuesModel.include? v } }
234
+ end
235
+ get '/proc' do
236
+ { type: params[:type] }
237
+ end
238
+
239
+ params do
240
+ requires :type, values: { proc: ->(v) { ValuesModel.include? v }, message: 'failed check' }
241
+ end
242
+ get '/proc/message'
243
+
244
+ params do
245
+ optional :name, type: String, values: %w[a b], allow_blank: true
246
+ end
247
+ get '/allow_blank'
248
+ end
238
249
  end
239
250
 
240
251
  context 'with a custom validation message' do
@@ -251,7 +262,7 @@ describe Grape::Validations::ValuesValidator do
251
262
  end
252
263
 
253
264
  it 'validates against values in a proc' do
254
- ValidationsSpec::ValuesModel.add_value('valid-type4')
265
+ ValuesModel.add_value('valid-type4')
255
266
 
256
267
  get('/custom_message/lambda', type: 'valid-type4')
257
268
  expect(last_response.status).to eq 200
@@ -350,15 +361,14 @@ describe Grape::Validations::ValuesValidator do
350
361
  end
351
362
 
352
363
  it 'does not validate updated values without proc' do
353
- ValidationsSpec::ValuesModel.add_value('valid-type4')
354
-
364
+ ValuesModel.add_value('valid-type4')
355
365
  get('/', type: 'valid-type4')
356
366
  expect(last_response.status).to eq 400
357
367
  expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
358
368
  end
359
369
 
360
370
  it 'validates against values in a proc' do
361
- ValidationsSpec::ValuesModel.add_value('valid-type4')
371
+ ValuesModel.add_value('valid-type4')
362
372
 
363
373
  get('/lambda', type: 'valid-type4')
364
374
  expect(last_response.status).to eq 200
@@ -371,6 +381,18 @@ describe Grape::Validations::ValuesValidator do
371
381
  expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
372
382
  end
373
383
 
384
+ it 'validates against values in an endless range', if: ActiveSupport::VERSION::MAJOR >= 6 do
385
+ get('/endless', type: 10)
386
+ expect(last_response.status).to eq 200
387
+ expect(last_response.body).to eq({ type: 10 }.to_json)
388
+ end
389
+
390
+ it 'does not allow an invalid value for a parameter using an endless range', if: ActiveSupport::VERSION::MAJOR >= 6 do
391
+ get('/endless', type: 0)
392
+ expect(last_response.status).to eq 400
393
+ expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
394
+ end
395
+
374
396
  it 'does not allow non-numeric string value for int value using lambda' do
375
397
  get('/lambda_int_val', number: 'foo')
376
398
  expect(last_response.status).to eq 400
@@ -420,21 +442,21 @@ describe Grape::Validations::ValuesValidator do
420
442
  it 'raises IncompatibleOptionValues on an invalid default value from proc' do
421
443
  subject = Class.new(Grape::API)
422
444
  expect do
423
- subject.params { optional :type, values: ['valid-type1', 'valid-type2', 'valid-type3'], default: ValidationsSpec::ValuesModel.values.sample + '_invalid' }
445
+ subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], default: "#{ValuesModel.values.sample}_invalid" }
424
446
  end.to raise_error Grape::Exceptions::IncompatibleOptionValues
425
447
  end
426
448
 
427
449
  it 'raises IncompatibleOptionValues on an invalid default value' do
428
450
  subject = Class.new(Grape::API)
429
451
  expect do
430
- subject.params { optional :type, values: ['valid-type1', 'valid-type2', 'valid-type3'], default: 'invalid-type' }
452
+ subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], default: 'invalid-type' }
431
453
  end.to raise_error Grape::Exceptions::IncompatibleOptionValues
432
454
  end
433
455
 
434
456
  it 'raises IncompatibleOptionValues when type is incompatible with values array' do
435
457
  subject = Class.new(Grape::API)
436
458
  expect do
437
- subject.params { optional :type, values: ['valid-type1', 'valid-type2', 'valid-type3'], type: Symbol }
459
+ subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], type: Symbol }
438
460
  end.to raise_error Grape::Exceptions::IncompatibleOptionValues
439
461
  end
440
462
 
@@ -648,9 +670,9 @@ describe Grape::Validations::ValuesValidator do
648
670
  end
649
671
 
650
672
  it 'accepts multiple valid values' do
651
- get '/proc', type: ['valid-type1', 'valid-type3']
673
+ get '/proc', type: %w[valid-type1 valid-type3]
652
674
  expect(last_response.status).to eq 200
653
- expect(last_response.body).to eq({ type: ['valid-type1', 'valid-type3'] }.to_json)
675
+ expect(last_response.body).to eq({ type: %w[valid-type1 valid-type3] }.to_json)
654
676
  end
655
677
 
656
678
  it 'rejects a single invalid value' do
@@ -660,7 +682,7 @@ describe Grape::Validations::ValuesValidator do
660
682
  end
661
683
 
662
684
  it 'rejects an invalid value among valid ones' do
663
- get '/proc', type: ['valid-type1', 'invalid-type1', 'valid-type3']
685
+ get '/proc', type: %w[valid-type1 invalid-type1 valid-type3]
664
686
  expect(last_response.status).to eq 400
665
687
  expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
666
688
  end