grape 1.5.3 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +67 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +150 -21
- data/UPGRADING.md +61 -4
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +14 -18
- data/lib/grape/api.rb +17 -12
- 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 +20 -35
- 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/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/path.rb +1 -0
- data/lib/grape/request.rb +3 -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 -0
- 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 +69 -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 +457 -231
- 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 +86 -58
- 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 +23 -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 +126 -117
- 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
|