grape 1.5.2 → 1.7.0
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 +75 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +152 -21
- data/UPGRADING.md +86 -2
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +14 -18
- data/lib/grape/api.rb +18 -13
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/api.rb +0 -2
- data/lib/grape/dsl/callbacks.rb +0 -2
- data/lib/grape/dsl/configuration.rb +0 -2
- data/lib/grape/dsl/desc.rb +2 -19
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -7
- data/lib/grape/dsl/inside_route.rb +43 -30
- data/lib/grape/dsl/middleware.rb +4 -6
- data/lib/grape/dsl/parameters.rb +8 -10
- data/lib/grape/dsl/request_response.rb +9 -8
- data/lib/grape/dsl/routing.rb +6 -4
- data/lib/grape/dsl/settings.rb +5 -7
- data/lib/grape/dsl/validations.rb +0 -15
- data/lib/grape/endpoint.rb +21 -36
- data/lib/grape/error_formatter/json.rb +9 -7
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/missing_group_type.rb +8 -1
- data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
- data/lib/grape/exceptions/validation.rb +1 -6
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/locale/en.yml +9 -8
- data/lib/grape/middleware/auth/dsl.rb +7 -2
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +2 -2
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +5 -0
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_doc.rb +58 -0
- data/lib/grape/validations/params_scope.rb +137 -78
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +16 -8
- data/lib/grape/validations/types/set_coercer.rb +0 -2
- data/lib/grape/validations/types.rb +98 -30
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +82 -70
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/validations.rb +16 -6
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +70 -29
- data/spec/grape/api/custom_validations_spec.rb +116 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -5
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
- data/spec/grape/api/documentation_spec.rb +59 -0
- data/spec/grape/api/inherited_helpers_spec.rb +0 -2
- data/spec/grape/api/instance_spec.rb +0 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -2
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/nested_helpers_spec.rb +0 -2
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/parameters_modification_spec.rb +0 -2
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
- data/spec/grape/api/recognize_path_spec.rb +1 -3
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
- data/spec/grape/api/shared_helpers_spec.rb +0 -2
- data/spec/grape/api_remount_spec.rb +16 -16
- data/spec/grape/api_spec.rb +527 -224
- data/spec/grape/config_spec.rb +0 -2
- data/spec/grape/dsl/callbacks_spec.rb +2 -3
- data/spec/grape/dsl/configuration_spec.rb +0 -2
- data/spec/grape/dsl/desc_spec.rb +0 -2
- data/spec/grape/dsl/headers_spec.rb +39 -11
- data/spec/grape/dsl/helpers_spec.rb +3 -4
- data/spec/grape/dsl/inside_route_spec.rb +16 -16
- data/spec/grape/dsl/logger_spec.rb +15 -19
- data/spec/grape/dsl/middleware_spec.rb +2 -3
- data/spec/grape/dsl/parameters_spec.rb +2 -2
- data/spec/grape/dsl/request_response_spec.rb +7 -8
- data/spec/grape/dsl/routing_spec.rb +11 -10
- data/spec/grape/dsl/settings_spec.rb +0 -2
- data/spec/grape/dsl/validations_spec.rb +0 -17
- data/spec/grape/endpoint/declared_spec.rb +261 -16
- data/spec/grape/endpoint_spec.rb +98 -57
- data/spec/grape/entity_spec.rb +22 -23
- data/spec/grape/exceptions/base_spec.rb +16 -2
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
- data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
- data/spec/grape/exceptions/missing_option_spec.rb +1 -3
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
- data/spec/grape/exceptions/validation_spec.rb +5 -5
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
- data/spec/grape/integration/rack_spec.rb +0 -2
- data/spec/grape/loading_spec.rb +8 -10
- data/spec/grape/middleware/auth/base_spec.rb +0 -1
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
- data/spec/grape/middleware/base_spec.rb +24 -17
- data/spec/grape/middleware/error_spec.rb +8 -3
- data/spec/grape/middleware/exception_spec.rb +111 -163
- data/spec/grape/middleware/formatter_spec.rb +27 -8
- data/spec/grape/middleware/globals_spec.rb +7 -6
- data/spec/grape/middleware/stack_spec.rb +14 -14
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
- data/spec/grape/middleware/versioner/header_spec.rb +30 -15
- data/spec/grape/middleware/versioner/param_spec.rb +7 -3
- data/spec/grape/middleware/versioner/path_spec.rb +5 -3
- data/spec/grape/middleware/versioner_spec.rb +1 -3
- data/spec/grape/named_api_spec.rb +0 -2
- data/spec/grape/parser_spec.rb +4 -2
- data/spec/grape/path_spec.rb +52 -54
- data/spec/grape/presenters/presenter_spec.rb +7 -8
- data/spec/grape/request_spec.rb +6 -6
- data/spec/grape/util/inheritable_setting_spec.rb +7 -8
- data/spec/grape/util/inheritable_values_spec.rb +3 -3
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
- data/spec/grape/util/stackable_values_spec.rb +7 -6
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
- data/spec/grape/validations/attributes_doc_spec.rb +153 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
- data/spec/grape/validations/params_scope_spec.rb +361 -96
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
- data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
- data/spec/grape/validations/types_spec.rb +36 -10
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
- data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
- data/spec/grape/validations/validators/coerce_spec.rb +99 -24
- data/spec/grape/validations/validators/default_spec.rb +72 -80
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
- data/spec/grape/validations/validators/except_values_spec.rb +3 -5
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
- data/spec/grape/validations/validators/presence_spec.rb +16 -3
- data/spec/grape/validations/validators/regexp_spec.rb +25 -33
- data/spec/grape/validations/validators/same_as_spec.rb +14 -22
- data/spec/grape/validations/validators/values_spec.rb +182 -179
- data/spec/grape/validations_spec.rb +149 -80
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -3
- data/spec/integration/multi_xml/xml_spec.rb +1 -3
- data/spec/shared/versioning_examples.rb +12 -9
- data/spec/spec_helper.rb +21 -6
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +125 -115
- data/lib/grape/validations/validators/all_or_none.rb +0 -15
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -16
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
- data/lib/grape/validations/validators/coerce.rb +0 -91
- data/lib/grape/validations/validators/default.rb +0 -48
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
- data/lib/grape/validations/validators/presence.rb +0 -12
- data/lib/grape/validations/validators/regexp.rb +0 -13
- data/lib/grape/validations/validators/same_as.rb +0 -26
- data/lib/grape/validations/validators/values.rb +0 -83
- data/spec/support/eager_load.rb +0 -19
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
3
|
describe Grape::Validations do
|
6
4
|
subject { Class.new(Grape::API) }
|
7
5
|
|
@@ -45,7 +43,7 @@ describe Grape::Validations do
|
|
45
43
|
subject.params do
|
46
44
|
optional :some_param
|
47
45
|
end
|
48
|
-
expect(declared_params).to eq([:some_param])
|
46
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([:some_param])
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -65,7 +63,7 @@ describe Grape::Validations do
|
|
65
63
|
|
66
64
|
it 'adds entity documentation to declared params' do
|
67
65
|
define_optional_using
|
68
|
-
expect(declared_params).to eq(%i[field_a field_b])
|
66
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[field_a field_b])
|
69
67
|
end
|
70
68
|
|
71
69
|
it 'works when field_a and field_b are not present' do
|
@@ -112,7 +110,7 @@ describe Grape::Validations do
|
|
112
110
|
subject.params do
|
113
111
|
requires :some_param
|
114
112
|
end
|
115
|
-
expect(declared_params).to eq([:some_param])
|
113
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([:some_param])
|
116
114
|
end
|
117
115
|
|
118
116
|
it 'works when required field is present but nil' do
|
@@ -197,7 +195,7 @@ describe Grape::Validations do
|
|
197
195
|
|
198
196
|
it 'adds entity documentation to declared params' do
|
199
197
|
define_requires_all
|
200
|
-
expect(declared_params).to eq(%i[required_field optional_field])
|
198
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[required_field optional_field])
|
201
199
|
end
|
202
200
|
|
203
201
|
it 'errors when required_field is not present' do
|
@@ -232,7 +230,7 @@ describe Grape::Validations do
|
|
232
230
|
|
233
231
|
it 'adds entity documentation to declared params' do
|
234
232
|
define_requires_none
|
235
|
-
expect(declared_params).to eq(%i[required_field optional_field])
|
233
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[required_field optional_field])
|
236
234
|
end
|
237
235
|
|
238
236
|
it 'errors when required_field is not present' do
|
@@ -262,7 +260,7 @@ describe Grape::Validations do
|
|
262
260
|
|
263
261
|
it 'adds only the entity documentation to declared params, nothing more' do
|
264
262
|
define_requires_all
|
265
|
-
expect(declared_params).to eq(%i[required_field optional_field])
|
263
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[required_field optional_field])
|
266
264
|
end
|
267
265
|
end
|
268
266
|
|
@@ -328,7 +326,7 @@ describe Grape::Validations do
|
|
328
326
|
requires :key
|
329
327
|
end
|
330
328
|
end
|
331
|
-
expect(declared_params).to eq([items: [:key]])
|
329
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
|
332
330
|
end
|
333
331
|
end
|
334
332
|
|
@@ -400,7 +398,7 @@ describe Grape::Validations do
|
|
400
398
|
requires :key
|
401
399
|
end
|
402
400
|
end
|
403
|
-
expect(declared_params).to eq([items: [:key]])
|
401
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
|
404
402
|
end
|
405
403
|
end
|
406
404
|
|
@@ -463,7 +461,7 @@ describe Grape::Validations do
|
|
463
461
|
requires :key
|
464
462
|
end
|
465
463
|
end
|
466
|
-
expect(declared_params).to eq([items: [:key]])
|
464
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
|
467
465
|
end
|
468
466
|
end
|
469
467
|
|
@@ -489,17 +487,24 @@ describe Grape::Validations do
|
|
489
487
|
end
|
490
488
|
|
491
489
|
context 'custom validator for a Hash' do
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
end
|
490
|
+
let(:date_range_validator) do
|
491
|
+
Class.new(Grape::Validations::Validators::Base) do
|
492
|
+
def validate_param!(attr_name, params)
|
493
|
+
return if params[attr_name][:from] <= params[attr_name][:to]
|
494
|
+
|
495
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "'from' must be lower or equal to 'to'")
|
499
496
|
end
|
500
497
|
end
|
501
498
|
end
|
502
499
|
|
500
|
+
before do
|
501
|
+
described_class.register_validator('date_range', date_range_validator)
|
502
|
+
end
|
503
|
+
|
504
|
+
after do
|
505
|
+
described_class.deregister_validator('date_range')
|
506
|
+
end
|
507
|
+
|
503
508
|
before do
|
504
509
|
subject.params do
|
505
510
|
optional :date_range, date_range: true, type: Hash do
|
@@ -817,7 +822,7 @@ describe Grape::Validations do
|
|
817
822
|
requires :key
|
818
823
|
end
|
819
824
|
end
|
820
|
-
expect(declared_params).to eq([items: [:key]])
|
825
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
|
821
826
|
end
|
822
827
|
end
|
823
828
|
|
@@ -881,19 +886,19 @@ describe Grape::Validations do
|
|
881
886
|
requires(:required_subitems, type: Array) { requires :value }
|
882
887
|
end
|
883
888
|
end
|
884
|
-
expect(declared_params).to eq([items: [:key, { optional_subitems: [:value] }, { required_subitems: [:value] }]])
|
889
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key, { optional_subitems: [:value] }, { required_subitems: [:value] }]])
|
885
890
|
end
|
886
891
|
|
887
892
|
context <<~DESC do
|
888
893
|
Issue occurs whenever:
|
889
894
|
* param structure with at least three levels
|
890
|
-
* 1st level item is a required Array that has >1 entry with an optional item present and >1 entry with an optional item missing
|
891
|
-
* 2nd level is an optional Array or Hash
|
895
|
+
* 1st level item is a required Array that has >1 entry with an optional item present and >1 entry with an optional item missing#{' '}
|
896
|
+
* 2nd level is an optional Array or Hash#{' '}
|
892
897
|
* 3rd level is a required item (can be any type)
|
893
898
|
* additional levels do not effect the issue from occuring
|
894
899
|
DESC
|
895
900
|
|
896
|
-
it
|
901
|
+
it 'example based off actual real world use case' do
|
897
902
|
subject.params do
|
898
903
|
requires :orders, type: Array do
|
899
904
|
requires :id, type: Integer
|
@@ -911,17 +916,17 @@ describe Grape::Validations do
|
|
911
916
|
|
912
917
|
data = {
|
913
918
|
orders: [
|
914
|
-
{ id: 77, drugs: [{batches: [{batch_no:
|
919
|
+
{ id: 77, drugs: [{ batches: [{ batch_no: 'A1234567' }] }] },
|
915
920
|
{ id: 70 }
|
916
921
|
]
|
917
922
|
}
|
918
923
|
|
919
924
|
get '/validate_required_arrays_under_optional_arrays', data
|
920
|
-
expect(last_response.body).to eq(
|
925
|
+
expect(last_response.body).to eq('validate_required_arrays_under_optional_arrays works!')
|
921
926
|
expect(last_response.status).to eq(200)
|
922
927
|
end
|
923
928
|
|
924
|
-
it
|
929
|
+
it 'simplest example using Array -> Array -> Hash -> String' do
|
925
930
|
subject.params do
|
926
931
|
requires :orders, type: Array do
|
927
932
|
requires :id, type: Integer
|
@@ -937,17 +942,17 @@ describe Grape::Validations do
|
|
937
942
|
|
938
943
|
data = {
|
939
944
|
orders: [
|
940
|
-
{ id: 77, drugs: [{batch_no:
|
945
|
+
{ id: 77, drugs: [{ batch_no: 'A1234567' }] },
|
941
946
|
{ id: 70 }
|
942
947
|
]
|
943
948
|
}
|
944
949
|
|
945
950
|
get '/validate_required_arrays_under_optional_arrays', data
|
946
|
-
expect(last_response.body).to eq(
|
951
|
+
expect(last_response.body).to eq('validate_required_arrays_under_optional_arrays works!')
|
947
952
|
expect(last_response.status).to eq(200)
|
948
953
|
end
|
949
954
|
|
950
|
-
it
|
955
|
+
it 'simplest example using Array -> Hash -> String' do
|
951
956
|
subject.params do
|
952
957
|
requires :orders, type: Array do
|
953
958
|
requires :id, type: Integer
|
@@ -963,17 +968,17 @@ describe Grape::Validations do
|
|
963
968
|
|
964
969
|
data = {
|
965
970
|
orders: [
|
966
|
-
{ id: 77, drugs: {batch_no:
|
971
|
+
{ id: 77, drugs: { batch_no: 'A1234567' } },
|
967
972
|
{ id: 70 }
|
968
973
|
]
|
969
974
|
}
|
970
975
|
|
971
976
|
get '/validate_required_arrays_under_optional_arrays', data
|
972
|
-
expect(last_response.body).to eq(
|
977
|
+
expect(last_response.body).to eq('validate_required_arrays_under_optional_arrays works!')
|
973
978
|
expect(last_response.status).to eq(200)
|
974
979
|
end
|
975
980
|
|
976
|
-
it
|
981
|
+
it 'correctly indexes invalida data' do
|
977
982
|
subject.params do
|
978
983
|
requires :orders, type: Array do
|
979
984
|
requires :id, type: Integer
|
@@ -991,16 +996,16 @@ describe Grape::Validations do
|
|
991
996
|
data = {
|
992
997
|
orders: [
|
993
998
|
{ id: 70 },
|
994
|
-
{ id: 77, drugs: [{batch_no:
|
999
|
+
{ id: 77, drugs: [{ batch_no: 'A1234567', quantity: 12 }, { batch_no: 'B222222' }] }
|
995
1000
|
]
|
996
1001
|
}
|
997
1002
|
|
998
1003
|
get '/correctly_indexes', data
|
999
|
-
expect(last_response.body).to eq(
|
1004
|
+
expect(last_response.body).to eq('orders[1][drugs][1][quantity] is missing')
|
1000
1005
|
expect(last_response.status).to eq(400)
|
1001
1006
|
end
|
1002
1007
|
|
1003
|
-
context
|
1008
|
+
context 'multiple levels of optional and requires settings' do
|
1004
1009
|
before do
|
1005
1010
|
subject.params do
|
1006
1011
|
requires :top, type: Array do
|
@@ -1022,53 +1027,62 @@ describe Grape::Validations do
|
|
1022
1027
|
end
|
1023
1028
|
end
|
1024
1029
|
|
1025
|
-
it
|
1030
|
+
it 'with valid data' do
|
1026
1031
|
data = {
|
1027
1032
|
top: [
|
1028
1033
|
{ top_id: 1, middle_1: [
|
1029
|
-
{middle_1_id: 11}, {middle_1_id: 12, middle_2: [
|
1030
|
-
{middle_2_id: 121}, {middle_2_id: 122, bottom: [{bottom_id: 1221}]}
|
1034
|
+
{ middle_1_id: 11 }, { middle_1_id: 12, middle_2: [
|
1035
|
+
{ middle_2_id: 121 }, { middle_2_id: 122, bottom: [{ bottom_id: 1221 }] }
|
1036
|
+
] }
|
1037
|
+
] },
|
1031
1038
|
{ top_id: 2, middle_1: [
|
1032
|
-
{middle_1_id: 21}, {middle_1_id: 22, middle_2: [
|
1033
|
-
|
1039
|
+
{ middle_1_id: 21 }, { middle_1_id: 22, middle_2: [
|
1040
|
+
{ middle_2_id: 221 }
|
1041
|
+
] }
|
1042
|
+
] },
|
1034
1043
|
{ top_id: 3, middle_1: [
|
1035
|
-
{middle_1_id: 31}, {middle_1_id: 32}
|
1044
|
+
{ middle_1_id: 31 }, { middle_1_id: 32 }
|
1045
|
+
] },
|
1036
1046
|
{ top_id: 4 }
|
1037
1047
|
]
|
1038
1048
|
}
|
1039
1049
|
|
1040
1050
|
get '/multi_level', data
|
1041
|
-
expect(last_response.body).to eq(
|
1051
|
+
expect(last_response.body).to eq('multi_level works!')
|
1042
1052
|
expect(last_response.status).to eq(200)
|
1043
1053
|
end
|
1044
1054
|
|
1045
|
-
it
|
1055
|
+
it 'with invalid data' do
|
1046
1056
|
data = {
|
1047
1057
|
top: [
|
1048
1058
|
{ top_id: 1, middle_1: [
|
1049
|
-
{middle_1_id: 11}, {middle_1_id: 12, middle_2: [
|
1050
|
-
|
1059
|
+
{ middle_1_id: 11 }, { middle_1_id: 12, middle_2: [
|
1060
|
+
{ middle_2_id: 121 }, { middle_2_id: 122, bottom: [{ bottom_id: nil }] }
|
1061
|
+
] }
|
1062
|
+
] },
|
1051
1063
|
{ top_id: 2, middle_1: [
|
1052
|
-
{middle_1_id: 21}, {middle_1_id: 22, middle_2: [{middle_2_id: nil}]}
|
1064
|
+
{ middle_1_id: 21 }, { middle_1_id: 22, middle_2: [{ middle_2_id: nil }] }
|
1065
|
+
] },
|
1053
1066
|
{ top_id: 3, middle_1: [
|
1054
|
-
{middle_1_id: nil}, {middle_1_id: 32}
|
1067
|
+
{ middle_1_id: nil }, { middle_1_id: 32 }
|
1068
|
+
] },
|
1055
1069
|
{ top_id: nil, missing_top_id: 4 }
|
1056
1070
|
]
|
1057
1071
|
}
|
1058
1072
|
# debugger
|
1059
1073
|
get '/multi_level', data
|
1060
|
-
expect(last_response.body.split(
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1074
|
+
expect(last_response.body.split(', ')).to match_array([
|
1075
|
+
'top[3][top_id] is empty',
|
1076
|
+
'top[2][middle_1][0][middle_1_id] is empty',
|
1077
|
+
'top[1][middle_1][1][middle_2][0][middle_2_id] is empty',
|
1078
|
+
'top[0][middle_1][1][middle_2][1][bottom][0][bottom_id] is empty'
|
1079
|
+
])
|
1066
1080
|
expect(last_response.status).to eq(400)
|
1067
1081
|
end
|
1068
1082
|
end
|
1069
1083
|
end
|
1070
1084
|
|
1071
|
-
it
|
1085
|
+
it 'exactly_one_of' do
|
1072
1086
|
subject.params do
|
1073
1087
|
requires :orders, type: Array do
|
1074
1088
|
requires :id, type: Integer
|
@@ -1086,17 +1100,17 @@ describe Grape::Validations do
|
|
1086
1100
|
|
1087
1101
|
data = {
|
1088
1102
|
orders: [
|
1089
|
-
{ id: 77, drugs: {batch_no:
|
1103
|
+
{ id: 77, drugs: { batch_no: 'A1234567' } },
|
1090
1104
|
{ id: 70 }
|
1091
1105
|
]
|
1092
1106
|
}
|
1093
1107
|
|
1094
1108
|
get '/exactly_one_of', data
|
1095
|
-
expect(last_response.body).to eq(
|
1109
|
+
expect(last_response.body).to eq('exactly_one_of works!')
|
1096
1110
|
expect(last_response.status).to eq(200)
|
1097
1111
|
end
|
1098
1112
|
|
1099
|
-
it
|
1113
|
+
it 'at_least_one_of' do
|
1100
1114
|
subject.params do
|
1101
1115
|
requires :orders, type: Array do
|
1102
1116
|
requires :id, type: Integer
|
@@ -1114,17 +1128,17 @@ describe Grape::Validations do
|
|
1114
1128
|
|
1115
1129
|
data = {
|
1116
1130
|
orders: [
|
1117
|
-
{ id: 77, drugs: {batch_no:
|
1131
|
+
{ id: 77, drugs: { batch_no: 'A1234567' } },
|
1118
1132
|
{ id: 70 }
|
1119
1133
|
]
|
1120
1134
|
}
|
1121
1135
|
|
1122
1136
|
get '/at_least_one_of', data
|
1123
|
-
expect(last_response.body).to eq(
|
1137
|
+
expect(last_response.body).to eq('at_least_one_of works!')
|
1124
1138
|
expect(last_response.status).to eq(200)
|
1125
1139
|
end
|
1126
1140
|
|
1127
|
-
it
|
1141
|
+
it 'all_or_none_of' do
|
1128
1142
|
subject.params do
|
1129
1143
|
requires :orders, type: Array do
|
1130
1144
|
requires :id, type: Integer
|
@@ -1142,13 +1156,13 @@ describe Grape::Validations do
|
|
1142
1156
|
|
1143
1157
|
data = {
|
1144
1158
|
orders: [
|
1145
|
-
{ id: 77, drugs: {batch_no:
|
1159
|
+
{ id: 77, drugs: { batch_no: 'A1234567', batch_id: '12' } },
|
1146
1160
|
{ id: 70 }
|
1147
1161
|
]
|
1148
1162
|
}
|
1149
1163
|
|
1150
1164
|
get '/all_or_none_of', data
|
1151
|
-
expect(last_response.body).to eq(
|
1165
|
+
expect(last_response.body).to eq('all_or_none_of works!')
|
1152
1166
|
expect(last_response.status).to eq(200)
|
1153
1167
|
end
|
1154
1168
|
end
|
@@ -1173,15 +1187,24 @@ describe Grape::Validations do
|
|
1173
1187
|
end
|
1174
1188
|
|
1175
1189
|
context 'custom validation' do
|
1176
|
-
|
1177
|
-
|
1190
|
+
let(:custom_validator) do
|
1191
|
+
Class.new(Grape::Validations::Validators::Base) do
|
1178
1192
|
def validate_param!(attr_name, params)
|
1179
1193
|
return if params[attr_name] == 'im custom'
|
1194
|
+
|
1180
1195
|
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: 'is not custom!')
|
1181
1196
|
end
|
1182
1197
|
end
|
1183
1198
|
end
|
1184
1199
|
|
1200
|
+
before do
|
1201
|
+
described_class.register_validator('customvalidator', custom_validator)
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
after do
|
1205
|
+
described_class.deregister_validator('customvalidator')
|
1206
|
+
end
|
1207
|
+
|
1185
1208
|
context 'when using optional with a custom validator' do
|
1186
1209
|
before do
|
1187
1210
|
subject.params do
|
@@ -1321,15 +1344,24 @@ describe Grape::Validations do
|
|
1321
1344
|
end
|
1322
1345
|
|
1323
1346
|
context 'when using options on param' do
|
1324
|
-
|
1325
|
-
|
1347
|
+
let(:custom_validator_with_options) do
|
1348
|
+
Class.new(Grape::Validations::Validators::Base) do
|
1326
1349
|
def validate_param!(attr_name, params)
|
1327
1350
|
return if params[attr_name] == @option[:text]
|
1351
|
+
|
1328
1352
|
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
|
1329
1353
|
end
|
1330
1354
|
end
|
1331
1355
|
end
|
1332
1356
|
|
1357
|
+
before do
|
1358
|
+
described_class.register_validator('customvalidator_with_options', custom_validator_with_options)
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
after do
|
1362
|
+
described_class.deregister_validator('customvalidator_with_options')
|
1363
|
+
end
|
1364
|
+
|
1333
1365
|
before do
|
1334
1366
|
subject.params do
|
1335
1367
|
optional :custom, customvalidator_with_options: { text: 'im custom with options', message: 'is not custom with options!' }
|
@@ -1394,14 +1426,14 @@ describe Grape::Validations do
|
|
1394
1426
|
subject.params do
|
1395
1427
|
use :pagination
|
1396
1428
|
end
|
1397
|
-
expect(declared_params).to eq %i[page per_page]
|
1429
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq %i[page per_page]
|
1398
1430
|
end
|
1399
1431
|
|
1400
1432
|
it 'by #use with multiple params' do
|
1401
1433
|
subject.params do
|
1402
1434
|
use :pagination, :period
|
1403
1435
|
end
|
1404
|
-
expect(declared_params).to eq %i[page per_page start_date end_date]
|
1436
|
+
expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq %i[page per_page start_date end_date]
|
1405
1437
|
end
|
1406
1438
|
end
|
1407
1439
|
|
@@ -1424,21 +1456,25 @@ describe Grape::Validations do
|
|
1424
1456
|
}
|
1425
1457
|
end
|
1426
1458
|
end
|
1459
|
+
|
1427
1460
|
it 'returns defaults' do
|
1428
1461
|
get '/order'
|
1429
1462
|
expect(last_response.status).to eq(200)
|
1430
1463
|
expect(last_response.body).to eq({ order: :asc, order_by: :created_at }.to_json)
|
1431
1464
|
end
|
1465
|
+
|
1432
1466
|
it 'overrides default value for order' do
|
1433
1467
|
get '/order?order=desc'
|
1434
1468
|
expect(last_response.status).to eq(200)
|
1435
1469
|
expect(last_response.body).to eq({ order: :desc, order_by: :created_at }.to_json)
|
1436
1470
|
end
|
1471
|
+
|
1437
1472
|
it 'overrides default value for order_by' do
|
1438
1473
|
get '/order?order_by=name'
|
1439
1474
|
expect(last_response.status).to eq(200)
|
1440
1475
|
expect(last_response.body).to eq({ order: :asc, order_by: :name }.to_json)
|
1441
1476
|
end
|
1477
|
+
|
1442
1478
|
it 'fails with invalid value' do
|
1443
1479
|
get '/order?order=invalid'
|
1444
1480
|
expect(last_response.status).to eq(400)
|
@@ -1447,23 +1483,35 @@ describe Grape::Validations do
|
|
1447
1483
|
end
|
1448
1484
|
end
|
1449
1485
|
|
1450
|
-
context '
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1486
|
+
context 'with block and keyword argument' do
|
1487
|
+
before do
|
1488
|
+
subject.helpers do
|
1489
|
+
params :shared_params do |type:|
|
1490
|
+
optional :param, default: type
|
1491
|
+
end
|
1492
|
+
end
|
1493
|
+
subject.format :json
|
1454
1494
|
subject.params do
|
1455
|
-
|
1495
|
+
use :shared_params, type: 'value'
|
1456
1496
|
end
|
1457
|
-
subject.get '/' do
|
1497
|
+
subject.get '/shared_params' do
|
1498
|
+
{
|
1499
|
+
param: params[:param]
|
1500
|
+
}
|
1458
1501
|
end
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
it 'works' do
|
1505
|
+
get '/shared_params'
|
1459
1506
|
|
1460
|
-
expect(
|
1507
|
+
expect(last_response.status).to eq(200)
|
1508
|
+
expect(last_response.body).to eq({ param: 'value' }.to_json)
|
1461
1509
|
end
|
1462
1510
|
end
|
1463
1511
|
|
1464
1512
|
context 'all or none' do
|
1465
1513
|
context 'optional params' do
|
1466
|
-
before
|
1514
|
+
before do
|
1467
1515
|
subject.resource :custom_message do
|
1468
1516
|
params do
|
1469
1517
|
optional :beer
|
@@ -1476,17 +1524,20 @@ describe Grape::Validations do
|
|
1476
1524
|
end
|
1477
1525
|
end
|
1478
1526
|
end
|
1527
|
+
|
1479
1528
|
context 'with a custom validation message' do
|
1480
1529
|
it 'errors when any one is present' do
|
1481
1530
|
get '/custom_message/all_or_none', beer: 'string'
|
1482
1531
|
expect(last_response.status).to eq(400)
|
1483
1532
|
expect(last_response.body).to eq 'beer, wine, juice all params are required or none is required'
|
1484
1533
|
end
|
1534
|
+
|
1485
1535
|
it 'works when all params are present' do
|
1486
1536
|
get '/custom_message/all_or_none', beer: 'string', wine: 'anotherstring', juice: 'anotheranotherstring'
|
1487
1537
|
expect(last_response.status).to eq(200)
|
1488
1538
|
expect(last_response.body).to eq 'all_or_none works!'
|
1489
1539
|
end
|
1540
|
+
|
1490
1541
|
it 'works when none are present' do
|
1491
1542
|
get '/custom_message/all_or_none'
|
1492
1543
|
expect(last_response.status).to eq(200)
|
@@ -1650,7 +1701,7 @@ describe Grape::Validations do
|
|
1650
1701
|
|
1651
1702
|
context 'exactly one of' do
|
1652
1703
|
context 'params' do
|
1653
|
-
before
|
1704
|
+
before do
|
1654
1705
|
subject.resources :custom_message do
|
1655
1706
|
params do
|
1656
1707
|
optional :beer
|
@@ -1714,7 +1765,7 @@ describe Grape::Validations do
|
|
1714
1765
|
end
|
1715
1766
|
|
1716
1767
|
context 'nested params' do
|
1717
|
-
before
|
1768
|
+
before do
|
1718
1769
|
subject.params do
|
1719
1770
|
requires :nested, type: Hash do
|
1720
1771
|
optional :beer_nested
|
@@ -1756,7 +1807,7 @@ describe Grape::Validations do
|
|
1756
1807
|
|
1757
1808
|
context 'at least one of' do
|
1758
1809
|
context 'params' do
|
1759
|
-
before
|
1810
|
+
before do
|
1760
1811
|
subject.resources :custom_message do
|
1761
1812
|
params do
|
1762
1813
|
optional :beer
|
@@ -1820,7 +1871,7 @@ describe Grape::Validations do
|
|
1820
1871
|
end
|
1821
1872
|
|
1822
1873
|
context 'nested params' do
|
1823
|
-
before
|
1874
|
+
before do
|
1824
1875
|
subject.params do
|
1825
1876
|
requires :nested, type: Hash do
|
1826
1877
|
optional :beer
|
@@ -1934,4 +1985,22 @@ describe Grape::Validations do
|
|
1934
1985
|
end
|
1935
1986
|
end
|
1936
1987
|
end
|
1988
|
+
|
1989
|
+
describe 'require_validator' do
|
1990
|
+
subject { described_class.require_validator(short_name) }
|
1991
|
+
|
1992
|
+
context 'when found' do
|
1993
|
+
let(:short_name) { :presence }
|
1994
|
+
|
1995
|
+
it { is_expected.to be(Grape::Validations::Validators::PresenceValidator) }
|
1996
|
+
end
|
1997
|
+
|
1998
|
+
context 'when not found' do
|
1999
|
+
let(:short_name) { :test }
|
2000
|
+
|
2001
|
+
it 'raises an error' do
|
2002
|
+
expect { subject }.to raise_error(Grape::Exceptions::UnknownValidator)
|
2003
|
+
end
|
2004
|
+
end
|
2005
|
+
end
|
1937
2006
|
end
|
@@ -6,10 +6,10 @@ require 'grape'
|
|
6
6
|
describe Grape do
|
7
7
|
it 'eager_load!' do
|
8
8
|
require 'grape/eager_load'
|
9
|
-
expect {
|
9
|
+
expect { described_class.eager_load! }.not_to raise_error
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'compile!' do
|
13
|
-
expect { Class.new(Grape::API).compile! }.
|
13
|
+
expect { Class.new(Grape::API).compile! }.not_to raise_error
|
14
14
|
end
|
15
15
|
end
|