grape 1.2.5 → 1.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/README.md +7 -6
- data/UPGRADING.md +43 -0
- data/grape.gemspec +10 -1
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +8 -6
- data/lib/grape/api.rb +4 -2
- data/lib/grape/config.rb +2 -0
- data/lib/grape/content_types.rb +34 -0
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/api.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +2 -0
- data/lib/grape/dsl/configuration.rb +2 -0
- data/lib/grape/dsl/desc.rb +2 -0
- data/lib/grape/dsl/headers.rb +2 -0
- data/lib/grape/dsl/helpers.rb +4 -2
- data/lib/grape/dsl/inside_route.rb +15 -11
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +2 -0
- data/lib/grape/dsl/parameters.rb +8 -6
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +9 -5
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +2 -0
- data/lib/grape/eager_load.rb +2 -0
- data/lib/grape/endpoint.rb +13 -7
- data/lib/grape/error_formatter/base.rb +2 -0
- data/lib/grape/error_formatter/json.rb +2 -0
- data/lib/grape/error_formatter/txt.rb +2 -0
- data/lib/grape/error_formatter/xml.rb +2 -0
- data/lib/grape/error_formatter.rb +3 -1
- data/lib/grape/exceptions/base.rb +11 -13
- data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
- data/lib/grape/exceptions/invalid_formatter.rb +2 -0
- data/lib/grape/exceptions/invalid_message_body.rb +2 -0
- data/lib/grape/exceptions/invalid_response.rb +2 -0
- data/lib/grape/exceptions/invalid_version_header.rb +2 -0
- data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
- data/lib/grape/exceptions/method_not_allowed.rb +2 -0
- data/lib/grape/exceptions/missing_group_type.rb +2 -0
- data/lib/grape/exceptions/missing_mime_type.rb +2 -0
- data/lib/grape/exceptions/missing_option.rb +2 -0
- data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
- data/lib/grape/exceptions/unknown_options.rb +2 -0
- data/lib/grape/exceptions/unknown_parameter.rb +2 -0
- data/lib/grape/exceptions/unknown_validator.rb +2 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
- data/lib/grape/exceptions/validation.rb +3 -1
- data/lib/grape/exceptions/validation_array_errors.rb +2 -0
- data/lib/grape/exceptions/validation_errors.rb +13 -12
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
- data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
- data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
- data/lib/grape/extensions/hash.rb +2 -0
- data/lib/grape/extensions/hashie/mash.rb +2 -0
- data/lib/grape/formatter/json.rb +2 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -0
- data/lib/grape/formatter/txt.rb +2 -0
- data/lib/grape/formatter/xml.rb +2 -0
- data/lib/grape/formatter.rb +5 -3
- data/lib/grape/http/headers.rb +49 -18
- data/lib/grape/middleware/auth/base.rb +2 -0
- data/lib/grape/middleware/auth/dsl.rb +2 -0
- data/lib/grape/middleware/auth/strategies.rb +2 -0
- data/lib/grape/middleware/auth/strategy_info.rb +2 -0
- data/lib/grape/middleware/base.rb +5 -5
- data/lib/grape/middleware/error.rb +3 -1
- data/lib/grape/middleware/filter.rb +2 -0
- data/lib/grape/middleware/formatter.rb +5 -3
- data/lib/grape/middleware/globals.rb +2 -0
- data/lib/grape/middleware/helpers.rb +2 -0
- data/lib/grape/middleware/stack.rb +4 -1
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
- data/lib/grape/middleware/versioner/header.rb +5 -3
- data/lib/grape/middleware/versioner/param.rb +3 -1
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -0
- data/lib/grape/middleware/versioner/path.rb +3 -1
- data/lib/grape/middleware/versioner.rb +2 -0
- data/lib/grape/namespace.rb +14 -2
- data/lib/grape/parser/json.rb +2 -0
- data/lib/grape/parser/xml.rb +2 -0
- data/lib/grape/parser.rb +3 -1
- data/lib/grape/path.rb +13 -1
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +15 -8
- data/lib/grape/router/attribute_translator.rb +18 -8
- data/lib/grape/router/pattern.rb +20 -16
- data/lib/grape/router/route.rb +9 -4
- data/lib/grape/router.rb +26 -12
- data/lib/grape/serve_file/file_body.rb +2 -0
- data/lib/grape/serve_file/file_response.rb +2 -0
- data/lib/grape/serve_file/sendfile_response.rb +2 -0
- data/lib/grape/util/base_inheritable.rb +6 -0
- data/lib/grape/util/cache.rb +20 -0
- data/lib/grape/util/endpoint_configuration.rb +2 -0
- data/lib/grape/util/env.rb +19 -17
- data/lib/grape/util/inheritable_setting.rb +2 -0
- data/lib/grape/util/inheritable_values.rb +2 -0
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_block.rb +2 -0
- data/lib/grape/util/lazy_object.rb +43 -0
- data/lib/grape/util/lazy_value.rb +2 -0
- data/lib/grape/util/registrable.rb +2 -0
- data/lib/grape/util/reverse_stackable_values.rb +3 -1
- data/lib/grape/util/stackable_values.rb +9 -21
- data/lib/grape/util/strict_hash_configuration.rb +2 -0
- data/lib/grape/util/xml.rb +2 -0
- data/lib/grape/validations/attributes_iterator.rb +3 -3
- data/lib/grape/validations/multiple_attributes_iterator.rb +2 -0
- data/lib/grape/validations/params_scope.rb +24 -11
- data/lib/grape/validations/single_attribute_iterator.rb +13 -2
- data/lib/grape/validations/types/array_coercer.rb +56 -0
- data/lib/grape/validations/types/build_coercer.rb +49 -48
- data/lib/grape/validations/types/custom_type_coercer.rb +15 -49
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
- data/lib/grape/validations/types/dry_type_coercer.rb +41 -0
- data/lib/grape/validations/types/file.rb +11 -9
- data/lib/grape/validations/types/json.rb +11 -8
- data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
- data/lib/grape/validations/types/primitive_coercer.rb +61 -0
- data/lib/grape/validations/types/set_coercer.rb +38 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +4 -12
- data/lib/grape/validations/types.rb +7 -30
- data/lib/grape/validations/validator_factory.rb +2 -0
- data/lib/grape/validations/validators/all_or_none.rb +3 -1
- data/lib/grape/validations/validators/allow_blank.rb +3 -1
- data/lib/grape/validations/validators/as.rb +2 -0
- data/lib/grape/validations/validators/at_least_one_of.rb +3 -1
- data/lib/grape/validations/validators/base.rb +8 -5
- data/lib/grape/validations/validators/coerce.rb +44 -27
- data/lib/grape/validations/validators/default.rb +2 -0
- data/lib/grape/validations/validators/exactly_one_of.rb +6 -2
- data/lib/grape/validations/validators/except_values.rb +3 -1
- data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
- data/lib/grape/validations/validators/mutual_exclusion.rb +3 -1
- data/lib/grape/validations/validators/presence.rb +3 -1
- data/lib/grape/validations/validators/regexp.rb +3 -1
- data/lib/grape/validations/validators/same_as.rb +6 -3
- data/lib/grape/validations/validators/values.rb +17 -5
- data/lib/grape/validations.rb +2 -0
- data/lib/grape/version.rb +3 -1
- data/lib/grape.rb +4 -5
- data/spec/grape/api/custom_validations_spec.rb +5 -3
- data/spec/grape/api/deeply_included_options_spec.rb +2 -0
- data/spec/grape/api/defines_boolean_in_params_spec.rb +5 -3
- data/spec/grape/api/inherited_helpers_spec.rb +2 -0
- data/spec/grape/api/instance_spec.rb +54 -0
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/nested_helpers_spec.rb +2 -0
- data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/parameters_modification_spec.rb +3 -1
- data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +2 -0
- data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +2 -0
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
- data/spec/grape/api/shared_helpers_spec.rb +2 -0
- data/spec/grape/api_remount_spec.rb +2 -0
- data/spec/grape/api_spec.rb +34 -11
- data/spec/grape/config_spec.rb +2 -0
- data/spec/grape/dsl/callbacks_spec.rb +2 -0
- data/spec/grape/dsl/configuration_spec.rb +2 -0
- data/spec/grape/dsl/desc_spec.rb +2 -0
- data/spec/grape/dsl/headers_spec.rb +2 -0
- data/spec/grape/dsl/helpers_spec.rb +4 -2
- data/spec/grape/dsl/inside_route_spec.rb +2 -0
- data/spec/grape/dsl/logger_spec.rb +2 -0
- data/spec/grape/dsl/middleware_spec.rb +2 -0
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +2 -0
- data/spec/grape/dsl/routing_spec.rb +2 -0
- data/spec/grape/dsl/settings_spec.rb +2 -0
- data/spec/grape/dsl/validations_spec.rb +2 -0
- data/spec/grape/endpoint_spec.rb +3 -1
- data/spec/grape/entity_spec.rb +2 -0
- data/spec/grape/exceptions/base_spec.rb +3 -1
- data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_response_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
- data/spec/grape/exceptions/missing_option_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +4 -2
- data/spec/grape/exceptions/validation_spec.rb +3 -1
- data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
- data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
- data/spec/grape/integration/rack_sendfile_spec.rb +2 -0
- data/spec/grape/integration/rack_spec.rb +3 -1
- data/spec/grape/loading_spec.rb +2 -0
- data/spec/grape/middleware/auth/base_spec.rb +2 -0
- data/spec/grape/middleware/auth/dsl_spec.rb +2 -0
- data/spec/grape/middleware/auth/strategies_spec.rb +2 -0
- data/spec/grape/middleware/base_spec.rb +2 -0
- data/spec/grape/middleware/error_spec.rb +2 -0
- data/spec/grape/middleware/exception_spec.rb +3 -1
- data/spec/grape/middleware/formatter_spec.rb +19 -12
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +11 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/param_spec.rb +3 -1
- data/spec/grape/middleware/versioner/path_spec.rb +3 -1
- data/spec/grape/middleware/versioner_spec.rb +2 -0
- data/spec/grape/named_api_spec.rb +2 -0
- data/spec/grape/parser_spec.rb +7 -5
- data/spec/grape/path_spec.rb +2 -0
- data/spec/grape/presenters/presenter_spec.rb +2 -0
- data/spec/grape/request_spec.rb +2 -0
- data/spec/grape/util/inheritable_setting_spec.rb +2 -0
- data/spec/grape/util/inheritable_values_spec.rb +2 -0
- data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
- data/spec/grape/util/stackable_values_spec.rb +3 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
- data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +2 -0
- data/spec/grape/validations/params_scope_spec.rb +3 -1
- data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -4
- data/spec/grape/validations/types/primitive_coercer_spec.rb +75 -0
- data/spec/grape/validations/types_spec.rb +8 -35
- data/spec/grape/validations/validators/all_or_none_spec.rb +2 -0
- data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +2 -0
- data/spec/grape/validations/validators/coerce_spec.rb +51 -110
- data/spec/grape/validations/validators/default_spec.rb +2 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +14 -12
- data/spec/grape/validations/validators/except_values_spec.rb +3 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +2 -0
- data/spec/grape/validations/validators/presence_spec.rb +30 -0
- data/spec/grape/validations/validators/regexp_spec.rb +2 -0
- data/spec/grape/validations/validators/same_as_spec.rb +2 -0
- data/spec/grape/validations/validators/values_spec.rb +29 -4
- data/spec/grape/validations_spec.rb +69 -15
- data/spec/integration/multi_json/json_spec.rb +2 -0
- data/spec/integration/multi_xml/xml_spec.rb +2 -0
- data/spec/shared/versioning_examples.rb +2 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/content_type_helpers.rb +2 -0
- data/spec/support/eager_load.rb +19 -0
- data/spec/support/endpoint_faker.rb +2 -0
- data/spec/support/file_streamer.rb +2 -0
- data/spec/support/integer_helpers.rb +2 -0
- data/spec/support/versioned_helpers.rb +4 -2
- metadata +126 -112
- data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
- data/lib/grape/util/content_types.rb +0 -26
- data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Grape::Validations::CoerceValidator do
|
@@ -10,11 +12,13 @@ describe Grape::Validations::CoerceValidator do
|
|
10
12
|
end
|
11
13
|
|
12
14
|
describe 'coerce' do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
class SecureURIOnly
|
16
|
+
def self.parse(value)
|
17
|
+
URI.parse(value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.parsed?(value)
|
21
|
+
value.is_a? URI::HTTPS
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
@@ -96,6 +100,7 @@ describe Grape::Validations::CoerceValidator do
|
|
96
100
|
|
97
101
|
it 'respects :coerce_with' do
|
98
102
|
get '/', a: 'yup'
|
103
|
+
|
99
104
|
expect(last_response.status).to eq(200)
|
100
105
|
expect(last_response.body).to eq('TrueClass')
|
101
106
|
end
|
@@ -148,26 +153,20 @@ describe Grape::Validations::CoerceValidator do
|
|
148
153
|
expect(last_response.body).to eq('array int works')
|
149
154
|
end
|
150
155
|
|
151
|
-
context '
|
152
|
-
it '
|
156
|
+
context 'coerces' do
|
157
|
+
it 'BigDecimal' do
|
153
158
|
subject.params do
|
154
|
-
requires :
|
159
|
+
requires :bigdecimal, coerce: BigDecimal
|
155
160
|
end
|
156
|
-
subject.get '/
|
157
|
-
|
161
|
+
subject.get '/bigdecimal' do
|
162
|
+
params[:bigdecimal].class
|
158
163
|
end
|
159
164
|
|
160
|
-
get '/
|
161
|
-
expect(last_response.status).to eq(400)
|
162
|
-
expect(last_response.body).to eq('user is invalid')
|
163
|
-
|
164
|
-
get '/user', user: { id: 32, name: 'Bob' }
|
165
|
+
get '/bigdecimal', bigdecimal: '45'
|
165
166
|
expect(last_response.status).to eq(200)
|
166
|
-
expect(last_response.body).to eq('
|
167
|
+
expect(last_response.body).to eq('BigDecimal')
|
167
168
|
end
|
168
|
-
end
|
169
169
|
|
170
|
-
context 'coerces' do
|
171
170
|
it 'Integer' do
|
172
171
|
subject.params do
|
173
172
|
requires :int, coerce: Integer
|
@@ -181,6 +180,25 @@ describe Grape::Validations::CoerceValidator do
|
|
181
180
|
expect(last_response.body).to eq(integer_class_name)
|
182
181
|
end
|
183
182
|
|
183
|
+
it 'is a custom type' do
|
184
|
+
subject.params do
|
185
|
+
requires :uri, coerce: SecureURIOnly
|
186
|
+
end
|
187
|
+
subject.get '/secure_uri' do
|
188
|
+
params[:uri].class
|
189
|
+
end
|
190
|
+
|
191
|
+
get 'secure_uri', uri: 'https://www.example.com'
|
192
|
+
|
193
|
+
expect(last_response.status).to eq(200)
|
194
|
+
expect(last_response.body).to eq('URI::HTTPS')
|
195
|
+
|
196
|
+
get 'secure_uri', uri: 'http://www.example.com'
|
197
|
+
|
198
|
+
expect(last_response.status).to eq(400)
|
199
|
+
expect(last_response.body).to eq('uri is invalid')
|
200
|
+
end
|
201
|
+
|
184
202
|
context 'Array' do
|
185
203
|
it 'Array of Integers' do
|
186
204
|
subject.params do
|
@@ -197,7 +215,7 @@ describe Grape::Validations::CoerceValidator do
|
|
197
215
|
|
198
216
|
it 'Array of Bools' do
|
199
217
|
subject.params do
|
200
|
-
requires :arry, coerce: Array[
|
218
|
+
requires :arry, coerce: Array[Grape::API::Boolean]
|
201
219
|
end
|
202
220
|
subject.get '/array' do
|
203
221
|
params[:arry][0].class
|
@@ -208,27 +226,6 @@ describe Grape::Validations::CoerceValidator do
|
|
208
226
|
expect(last_response.body).to eq('TrueClass')
|
209
227
|
end
|
210
228
|
|
211
|
-
it 'Array of Complex' do
|
212
|
-
subject.params do
|
213
|
-
requires :arry, coerce: Array[CoerceValidatorSpec::User]
|
214
|
-
end
|
215
|
-
subject.get '/array' do
|
216
|
-
params[:arry].size
|
217
|
-
end
|
218
|
-
|
219
|
-
get 'array', arry: [31]
|
220
|
-
expect(last_response.status).to eq(400)
|
221
|
-
expect(last_response.body).to eq('arry is invalid')
|
222
|
-
|
223
|
-
get 'array', arry: { id: 31, name: 'Alice' }
|
224
|
-
expect(last_response.status).to eq(400)
|
225
|
-
expect(last_response.body).to eq('arry is invalid')
|
226
|
-
|
227
|
-
get 'array', arry: [{ id: 31, name: 'Alice' }]
|
228
|
-
expect(last_response.status).to eq(200)
|
229
|
-
expect(last_response.body).to eq('1')
|
230
|
-
end
|
231
|
-
|
232
229
|
it 'Array of type implementing parse' do
|
233
230
|
subject.params do
|
234
231
|
requires :uri, type: Array[URI]
|
@@ -253,17 +250,7 @@ describe Grape::Validations::CoerceValidator do
|
|
253
250
|
expect(last_response.body).to eq('Set,URI::HTTP,1')
|
254
251
|
end
|
255
252
|
|
256
|
-
it 'Array of
|
257
|
-
class SecureURIOnly
|
258
|
-
def self.parse(value)
|
259
|
-
URI.parse(value)
|
260
|
-
end
|
261
|
-
|
262
|
-
def self.parsed?(value)
|
263
|
-
value.is_a? URI::HTTPS
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
253
|
+
it 'Array of a custom type' do
|
267
254
|
subject.params do
|
268
255
|
requires :uri, type: Array[SecureURIOnly]
|
269
256
|
end
|
@@ -295,7 +282,7 @@ describe Grape::Validations::CoerceValidator do
|
|
295
282
|
|
296
283
|
it 'Set of Bools' do
|
297
284
|
subject.params do
|
298
|
-
requires :set, coerce: Set[
|
285
|
+
requires :set, coerce: Set[Grape::API::Boolean]
|
299
286
|
end
|
300
287
|
subject.get '/set' do
|
301
288
|
params[:set].first.class
|
@@ -307,66 +294,17 @@ describe Grape::Validations::CoerceValidator do
|
|
307
294
|
end
|
308
295
|
end
|
309
296
|
|
310
|
-
it 'Bool' do
|
311
|
-
subject.params do
|
312
|
-
requires :bool, coerce: Virtus::Attribute::Boolean
|
313
|
-
end
|
314
|
-
subject.get '/bool' do
|
315
|
-
params[:bool].class
|
316
|
-
end
|
317
|
-
|
318
|
-
get '/bool', bool: 1
|
319
|
-
expect(last_response.status).to eq(200)
|
320
|
-
expect(last_response.body).to eq('TrueClass')
|
321
|
-
|
322
|
-
get '/bool', bool: 0
|
323
|
-
expect(last_response.status).to eq(200)
|
324
|
-
expect(last_response.body).to eq('FalseClass')
|
325
|
-
|
326
|
-
get '/bool', bool: 'false'
|
327
|
-
expect(last_response.status).to eq(200)
|
328
|
-
expect(last_response.body).to eq('FalseClass')
|
329
|
-
|
330
|
-
get '/bool', bool: 'true'
|
331
|
-
expect(last_response.status).to eq(200)
|
332
|
-
expect(last_response.body).to eq('TrueClass')
|
333
|
-
end
|
334
|
-
|
335
297
|
it 'Boolean' do
|
336
298
|
subject.params do
|
337
|
-
|
299
|
+
requires :boolean, type: Boolean
|
338
300
|
end
|
339
301
|
subject.get '/boolean' do
|
340
302
|
params[:boolean].class
|
341
303
|
end
|
342
304
|
|
343
|
-
get '/boolean'
|
305
|
+
get '/boolean', boolean: 1
|
344
306
|
expect(last_response.status).to eq(200)
|
345
307
|
expect(last_response.body).to eq('TrueClass')
|
346
|
-
|
347
|
-
get '/boolean', boolean: true
|
348
|
-
expect(last_response.status).to eq(200)
|
349
|
-
expect(last_response.body).to eq('TrueClass')
|
350
|
-
|
351
|
-
get '/boolean', boolean: false
|
352
|
-
expect(last_response.status).to eq(200)
|
353
|
-
expect(last_response.body).to eq('FalseClass')
|
354
|
-
|
355
|
-
get '/boolean', boolean: 'true'
|
356
|
-
expect(last_response.status).to eq(200)
|
357
|
-
expect(last_response.body).to eq('TrueClass')
|
358
|
-
|
359
|
-
get '/boolean', boolean: 'false'
|
360
|
-
expect(last_response.status).to eq(200)
|
361
|
-
expect(last_response.body).to eq('FalseClass')
|
362
|
-
|
363
|
-
get '/boolean', boolean: 123
|
364
|
-
expect(last_response.status).to eq(400)
|
365
|
-
expect(last_response.body).to eq('boolean is invalid')
|
366
|
-
|
367
|
-
get '/boolean', boolean: '123'
|
368
|
-
expect(last_response.status).to eq(400)
|
369
|
-
expect(last_response.body).to eq('boolean is invalid')
|
370
308
|
end
|
371
309
|
|
372
310
|
it 'Rack::Multipart::UploadedFile' do
|
@@ -443,19 +381,19 @@ describe Grape::Validations::CoerceValidator do
|
|
443
381
|
|
444
382
|
it 'parses parameters with Array[String] type' do
|
445
383
|
subject.params do
|
446
|
-
requires :values, type: Array[String], coerce_with: ->(val) { val.split(/\s+/)
|
384
|
+
requires :values, type: Array[String], coerce_with: ->(val) { val.split(/\s+/) }
|
447
385
|
end
|
448
|
-
subject.get '/
|
386
|
+
subject.get '/strings' do
|
449
387
|
params[:values]
|
450
388
|
end
|
451
389
|
|
452
|
-
get '/
|
390
|
+
get '/strings', values: '1 2 3 4'
|
453
391
|
expect(last_response.status).to eq(200)
|
454
392
|
expect(JSON.parse(last_response.body)).to eq(%w[1 2 3 4])
|
455
393
|
|
456
|
-
get '/
|
394
|
+
get '/strings', values: 'a b c d'
|
457
395
|
expect(last_response.status).to eq(200)
|
458
|
-
expect(JSON.parse(last_response.body)).to eq(%w[
|
396
|
+
expect(JSON.parse(last_response.body)).to eq(%w[a b c d])
|
459
397
|
end
|
460
398
|
|
461
399
|
it 'parses parameters with Array[Integer] type' do
|
@@ -914,14 +852,17 @@ describe Grape::Validations::CoerceValidator do
|
|
914
852
|
end
|
915
853
|
|
916
854
|
context 'converter' do
|
917
|
-
it 'does not build
|
855
|
+
it 'does not build a coercer multiple times' do
|
918
856
|
subject.params do
|
919
857
|
requires :something, type: Array[String]
|
920
858
|
end
|
921
859
|
subject.get do
|
922
860
|
end
|
923
861
|
|
924
|
-
expect(
|
862
|
+
expect(Grape::Validations::Types::ArrayCoercer).to(
|
863
|
+
receive(:new).at_most(:once).and_call_original
|
864
|
+
)
|
865
|
+
|
925
866
|
10.times { get '/' }
|
926
867
|
end
|
927
868
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Grape::Validations::ExactlyOneOfValidator do
|
@@ -98,7 +100,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
98
100
|
validate
|
99
101
|
expect(last_response.status).to eq 400
|
100
102
|
expect(JSON.parse(last_response.body)).to eq(
|
101
|
-
'beer,wine,grapefruit' => ['are
|
103
|
+
'beer,wine,grapefruit' => ['are mutually exclusive']
|
102
104
|
)
|
103
105
|
end
|
104
106
|
|
@@ -110,7 +112,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
110
112
|
validate
|
111
113
|
expect(last_response.status).to eq 400
|
112
114
|
expect(JSON.parse(last_response.body)).to eq(
|
113
|
-
'beer,wine,grapefruit' => ['are
|
115
|
+
'beer,wine,grapefruit' => ['are mutually exclusive']
|
114
116
|
)
|
115
117
|
end
|
116
118
|
end
|
@@ -124,7 +126,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
124
126
|
validate
|
125
127
|
expect(last_response.status).to eq 400
|
126
128
|
expect(JSON.parse(last_response.body)).to eq(
|
127
|
-
'beer,
|
129
|
+
'beer,grapefruit' => ['are mutually exclusive']
|
128
130
|
)
|
129
131
|
end
|
130
132
|
end
|
@@ -137,7 +139,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
137
139
|
validate
|
138
140
|
expect(last_response.status).to eq 400
|
139
141
|
expect(JSON.parse(last_response.body)).to eq(
|
140
|
-
'beer,wine
|
142
|
+
'beer,wine' => ['you should choose one']
|
141
143
|
)
|
142
144
|
end
|
143
145
|
end
|
@@ -173,7 +175,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
173
175
|
validate
|
174
176
|
expect(last_response.status).to eq 400
|
175
177
|
expect(JSON.parse(last_response.body)).to eq(
|
176
|
-
'item[beer],item[wine]
|
178
|
+
'item[beer],item[wine]' => ['are mutually exclusive']
|
177
179
|
)
|
178
180
|
end
|
179
181
|
end
|
@@ -188,7 +190,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
188
190
|
validate
|
189
191
|
expect(last_response.status).to eq 400
|
190
192
|
expect(JSON.parse(last_response.body)).to eq(
|
191
|
-
'item[beer],item[wine]
|
193
|
+
'item[beer],item[wine]' => ['are mutually exclusive']
|
192
194
|
)
|
193
195
|
end
|
194
196
|
end
|
@@ -211,11 +213,11 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
211
213
|
validate
|
212
214
|
expect(last_response.status).to eq 400
|
213
215
|
expect(JSON.parse(last_response.body)).to eq(
|
214
|
-
'items[0][beer],items[0][wine]
|
215
|
-
'are
|
216
|
+
'items[0][beer],items[0][wine]' => [
|
217
|
+
'are mutually exclusive'
|
216
218
|
],
|
217
|
-
'items[1][
|
218
|
-
'are
|
219
|
+
'items[1][wine],items[1][grapefruit]' => [
|
220
|
+
'are mutually exclusive'
|
219
221
|
]
|
220
222
|
)
|
221
223
|
end
|
@@ -229,8 +231,8 @@ describe Grape::Validations::ExactlyOneOfValidator do
|
|
229
231
|
validate
|
230
232
|
expect(last_response.status).to eq 400
|
231
233
|
expect(JSON.parse(last_response.body)).to eq(
|
232
|
-
'items[0][nested_items][0][beer],items[0][nested_items][0][wine]
|
233
|
-
'are
|
234
|
+
'items[0][nested_items][0][beer],items[0][nested_items][0][wine]' => [
|
235
|
+
'are mutually exclusive'
|
234
236
|
]
|
235
237
|
)
|
236
238
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Grape::Validations::ExceptValuesValidator do
|
@@ -110,7 +112,7 @@ describe Grape::Validations::ExceptValuesValidator do
|
|
110
112
|
optional: { type: Array[Integer], except_values: [10, 11], default: 12 },
|
111
113
|
tests: [
|
112
114
|
{ value: 'invalid-type1', rc: 400, body: { error: 'type is invalid' }.to_json },
|
113
|
-
{ value: 10, rc: 400, body: { error: 'type
|
115
|
+
{ value: 10, rc: 400, body: { error: 'type is invalid' }.to_json },
|
114
116
|
{ value: [10], rc: 400, body: { error: 'type has a value not allowed' }.to_json },
|
115
117
|
{ value: ['3'], rc: 200, body: { type: [3] }.to_json },
|
116
118
|
{ value: [3], rc: 200, body: { type: [3] }.to_json },
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Grape::Validations::PresenceValidator do
|
@@ -269,4 +271,32 @@ describe Grape::Validations::PresenceValidator do
|
|
269
271
|
expect(last_response.body).to eq('Hello optional'.to_json)
|
270
272
|
end
|
271
273
|
end
|
274
|
+
|
275
|
+
context 'with a custom type' do
|
276
|
+
it 'does not validate their type when it is missing' do
|
277
|
+
class CustomType
|
278
|
+
def self.parse(value)
|
279
|
+
return if value.blank?
|
280
|
+
|
281
|
+
new
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
subject.params do
|
286
|
+
requires :custom, type: CustomType
|
287
|
+
end
|
288
|
+
subject.get '/custom' do
|
289
|
+
'custom'
|
290
|
+
end
|
291
|
+
|
292
|
+
get 'custom'
|
293
|
+
|
294
|
+
expect(last_response.status).to eq(400)
|
295
|
+
expect(last_response.body).to eq('{"error":"custom is missing"}')
|
296
|
+
|
297
|
+
get 'custom', custom: 'filled'
|
298
|
+
|
299
|
+
expect(last_response.status).to eq(200)
|
300
|
+
end
|
301
|
+
end
|
272
302
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Grape::Validations::ValuesValidator do
|
@@ -222,6 +224,11 @@ describe Grape::Validations::ValuesValidator do
|
|
222
224
|
requires :type, values: { proc: ->(v) { ValuesModel.values.include? v }, message: 'failed check' }
|
223
225
|
end
|
224
226
|
get '/proc/message'
|
227
|
+
|
228
|
+
params do
|
229
|
+
optional :name, type: String, values: %w[a b], allow_blank: true
|
230
|
+
end
|
231
|
+
get '/allow_blank'
|
225
232
|
end
|
226
233
|
end
|
227
234
|
end
|
@@ -431,11 +438,21 @@ describe Grape::Validations::ValuesValidator do
|
|
431
438
|
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
432
439
|
end
|
433
440
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
441
|
+
context 'boolean values' do
|
442
|
+
it 'allows a value from the list' do
|
443
|
+
get('/values/optional_boolean', type: true)
|
444
|
+
|
445
|
+
expect(last_response.status).to eq 200
|
446
|
+
expect(last_response.body).to eq({ type: true }.to_json)
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'rejects a value which is not in the list' do
|
450
|
+
get('/values/optional_boolean', type: false)
|
451
|
+
|
452
|
+
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
453
|
+
end
|
438
454
|
end
|
455
|
+
|
439
456
|
it 'allows values to be a kind of the coerced type not just an instance of it' do
|
440
457
|
get('/values/coercion', type: 10)
|
441
458
|
expect(last_response.status).to eq 200
|
@@ -462,6 +479,14 @@ describe Grape::Validations::ValuesValidator do
|
|
462
479
|
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
463
480
|
end
|
464
481
|
|
482
|
+
it 'allows a blank value when the allow_blank option is true' do
|
483
|
+
get 'allow_blank', name: nil
|
484
|
+
expect(last_response.status).to eq(200)
|
485
|
+
|
486
|
+
get 'allow_blank', name: ''
|
487
|
+
expect(last_response.status).to eq(200)
|
488
|
+
end
|
489
|
+
|
465
490
|
context 'with a lambda values' do
|
466
491
|
subject do
|
467
492
|
Class.new(Grape::API) do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Grape::Validations do
|
@@ -9,14 +11,17 @@ describe Grape::Validations do
|
|
9
11
|
|
10
12
|
describe 'params' do
|
11
13
|
context 'optional' do
|
12
|
-
|
14
|
+
before do
|
13
15
|
subject.params do
|
14
16
|
optional :a_number, regexp: /^[0-9]+$/
|
17
|
+
optional :attachment, type: File
|
15
18
|
end
|
16
19
|
subject.get '/optional' do
|
17
20
|
'optional works!'
|
18
21
|
end
|
22
|
+
end
|
19
23
|
|
24
|
+
it 'validates when params is present' do
|
20
25
|
get '/optional', a_number: 'string'
|
21
26
|
expect(last_response.status).to eq(400)
|
22
27
|
expect(last_response.body).to eq('a_number is invalid')
|
@@ -27,14 +32,7 @@ describe Grape::Validations do
|
|
27
32
|
end
|
28
33
|
|
29
34
|
it "doesn't validate when param not present" do
|
30
|
-
|
31
|
-
optional :a_number, regexp: /^[0-9]+$/
|
32
|
-
end
|
33
|
-
subject.get '/optional' do
|
34
|
-
'optional works!'
|
35
|
-
end
|
36
|
-
|
37
|
-
get '/optional'
|
35
|
+
get '/optional', a_number: nil, attachment: nil
|
38
36
|
expect(last_response.status).to eq(200)
|
39
37
|
expect(last_response.body).to eq('optional works!')
|
40
38
|
end
|
@@ -120,6 +118,62 @@ describe Grape::Validations do
|
|
120
118
|
end
|
121
119
|
end
|
122
120
|
|
121
|
+
context 'requires with nested params' do
|
122
|
+
before do
|
123
|
+
subject.params do
|
124
|
+
requires :first_level, type: Hash do
|
125
|
+
optional :second_level, type: Array do
|
126
|
+
requires :value, type: Integer
|
127
|
+
optional :name, type: String
|
128
|
+
optional :third_level, type: Array do
|
129
|
+
requires :value, type: Integer
|
130
|
+
optional :name, type: String
|
131
|
+
optional :fourth_level, type: Array do
|
132
|
+
requires :value, type: Integer
|
133
|
+
optional :name, type: String
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
subject.put('/required') { 'required works' }
|
140
|
+
end
|
141
|
+
|
142
|
+
let(:request_params) do
|
143
|
+
{
|
144
|
+
first_level: {
|
145
|
+
second_level: [
|
146
|
+
{ value: 1, name: 'Lisa' },
|
147
|
+
{
|
148
|
+
value: 2,
|
149
|
+
name: 'James',
|
150
|
+
third_level: [
|
151
|
+
{ value: 'three', name: 'Sophie' },
|
152
|
+
{
|
153
|
+
value: 4,
|
154
|
+
name: 'Jenny',
|
155
|
+
fourth_level: [
|
156
|
+
{ name: 'Samuel' }, { value: 6, name: 'Jane' }
|
157
|
+
]
|
158
|
+
}
|
159
|
+
]
|
160
|
+
}
|
161
|
+
]
|
162
|
+
}
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'validates correctly in deep nested params' do
|
167
|
+
put '/required', request_params.to_json, 'CONTENT_TYPE' => 'application/json'
|
168
|
+
|
169
|
+
expect(last_response.status).to eq(400)
|
170
|
+
expect(last_response.body).to eq(
|
171
|
+
'first_level[second_level][1][third_level][0][value] is invalid, ' \
|
172
|
+
'first_level[second_level][1][third_level][1][fourth_level][0][value] is missing'
|
173
|
+
)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
123
177
|
context 'requires :all using Grape::Entity documentation' do
|
124
178
|
def define_requires_all
|
125
179
|
documentation = {
|
@@ -436,7 +490,7 @@ describe Grape::Validations do
|
|
436
490
|
class DateRangeValidator < Grape::Validations::Base
|
437
491
|
def validate_param!(attr_name, params)
|
438
492
|
return if params[attr_name][:from] <= params[attr_name][:to]
|
439
|
-
raise Grape::Exceptions::Validation
|
493
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "'from' must be lower or equal to 'to'")
|
440
494
|
end
|
441
495
|
end
|
442
496
|
end
|
@@ -851,7 +905,7 @@ describe Grape::Validations do
|
|
851
905
|
class Customvalidator < Grape::Validations::Base
|
852
906
|
def validate_param!(attr_name, params)
|
853
907
|
return if params[attr_name] == 'im custom'
|
854
|
-
raise Grape::Exceptions::Validation
|
908
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: 'is not custom!')
|
855
909
|
end
|
856
910
|
end
|
857
911
|
end
|
@@ -999,7 +1053,7 @@ describe Grape::Validations do
|
|
999
1053
|
class CustomvalidatorWithOptions < Grape::Validations::Base
|
1000
1054
|
def validate_param!(attr_name, params)
|
1001
1055
|
return if params[attr_name] == @option[:text]
|
1002
|
-
raise Grape::Exceptions::Validation
|
1056
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
|
1003
1057
|
end
|
1004
1058
|
end
|
1005
1059
|
end
|
@@ -1364,7 +1418,7 @@ describe Grape::Validations do
|
|
1364
1418
|
it 'errors when two or more are present' do
|
1365
1419
|
get '/custom_message/exactly_one_of', beer: 'string', wine: 'anotherstring'
|
1366
1420
|
expect(last_response.status).to eq(400)
|
1367
|
-
expect(last_response.body).to eq 'beer, wine
|
1421
|
+
expect(last_response.body).to eq 'beer, wine are missing, exactly one parameter is required'
|
1368
1422
|
end
|
1369
1423
|
end
|
1370
1424
|
|
@@ -1383,7 +1437,7 @@ describe Grape::Validations do
|
|
1383
1437
|
it 'errors when two or more are present' do
|
1384
1438
|
get '/exactly_one_of', beer: 'string', wine: 'anotherstring'
|
1385
1439
|
expect(last_response.status).to eq(400)
|
1386
|
-
expect(last_response.body).to eq 'beer, wine
|
1440
|
+
expect(last_response.body).to eq 'beer, wine are mutually exclusive'
|
1387
1441
|
end
|
1388
1442
|
end
|
1389
1443
|
|
@@ -1423,7 +1477,7 @@ describe Grape::Validations do
|
|
1423
1477
|
it 'errors when two or more are present' do
|
1424
1478
|
get '/exactly_one_of_nested', nested: { beer_nested: 'string' }, nested2: [{ beer_nested2: 'string', wine_nested2: 'anotherstring' }]
|
1425
1479
|
expect(last_response.status).to eq(400)
|
1426
|
-
expect(last_response.body).to eq 'nested2[0][beer_nested2], nested2[0][wine_nested2]
|
1480
|
+
expect(last_response.body).to eq 'nested2[0][beer_nested2], nested2[0][wine_nested2] are mutually exclusive'
|
1427
1481
|
end
|
1428
1482
|
end
|
1429
1483
|
end
|