grape 1.6.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 +29 -1
- data/README.md +120 -19
- data/UPGRADING.md +15 -0
- data/lib/grape/api/instance.rb +1 -1
- 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 +0 -15
- data/lib/grape/dsl/helpers.rb +0 -2
- data/lib/grape/dsl/inside_route.rb +33 -29
- data/lib/grape/dsl/middleware.rb +0 -2
- data/lib/grape/dsl/parameters.rb +5 -7
- data/lib/grape/dsl/request_response.rb +0 -2
- data/lib/grape/dsl/routing.rb +4 -2
- data/lib/grape/dsl/settings.rb +0 -2
- data/lib/grape/dsl/validations.rb +0 -15
- data/lib/grape/error_formatter/json.rb +7 -1
- 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 +0 -4
- data/lib/grape/locale/en.yml +9 -8
- data/lib/grape/middleware/auth/dsl.rb +0 -1
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/request.rb +2 -0
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/validations/attributes_doc.rb +58 -0
- data/lib/grape/validations/params_scope.rb +66 -40
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +3 -7
- data/lib/grape/validations/types/primitive_coercer.rb +14 -6
- 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.rb → all_or_none_of_validator.rb} +0 -2
- data/lib/grape/validations/validators/{allow_blank.rb → allow_blank_validator.rb} +0 -0
- data/lib/grape/validations/validators/{as.rb → as_validator.rb} +0 -0
- data/lib/grape/validations/validators/{at_least_one_of.rb → at_least_one_of_validator.rb} +0 -2
- data/lib/grape/validations/validators/base.rb +7 -0
- data/lib/grape/validations/validators/{coerce.rb → coerce_validator.rb} +0 -0
- data/lib/grape/validations/validators/{default.rb → default_validator.rb} +0 -0
- data/lib/grape/validations/validators/{exactly_one_of.rb → exactly_one_of_validator.rb} +0 -2
- data/lib/grape/validations/validators/{except_values.rb → except_values_validator.rb} +0 -0
- data/lib/grape/validations/validators/{mutual_exclusion.rb → mutual_exclusion_validator.rb} +0 -2
- data/lib/grape/validations/validators/{presence.rb → presence_validator.rb} +0 -0
- data/lib/grape/validations/validators/{regexp.rb → regexp_validator.rb} +0 -0
- data/lib/grape/validations/validators/{same_as.rb → same_as_validator.rb} +0 -0
- data/lib/grape/validations/validators/{values.rb → values_validator.rb} +0 -0
- data/lib/grape/validations.rb +16 -12
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +66 -28
- data/spec/grape/api/custom_validations_spec.rb +41 -2
- data/spec/grape/api/deeply_included_options_spec.rb +0 -2
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -2
- 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 +0 -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 +0 -2
- 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 +0 -2
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -2
- data/spec/grape/api/shared_helpers_spec.rb +0 -2
- data/spec/grape/api_remount_spec.rb +0 -1
- data/spec/grape/api_spec.rb +18 -5
- data/spec/grape/config_spec.rb +0 -2
- data/spec/grape/dsl/callbacks_spec.rb +0 -2
- 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 +2 -4
- data/spec/grape/dsl/helpers_spec.rb +0 -2
- data/spec/grape/dsl/inside_route_spec.rb +10 -12
- data/spec/grape/dsl/logger_spec.rb +0 -2
- data/spec/grape/dsl/middleware_spec.rb +0 -2
- data/spec/grape/dsl/parameters_spec.rb +0 -2
- data/spec/grape/dsl/request_response_spec.rb +6 -8
- data/spec/grape/dsl/routing_spec.rb +1 -3
- 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 +2 -4
- data/spec/grape/endpoint_spec.rb +22 -3
- data/spec/grape/entity_spec.rb +0 -1
- data/spec/grape/exceptions/base_spec.rb +16 -2
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -2
- 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 +0 -1
- data/spec/grape/exceptions/validation_spec.rb +1 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -2
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -2
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -2
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -2
- data/spec/grape/integration/rack_spec.rb +0 -2
- data/spec/grape/loading_spec.rb +0 -2
- data/spec/grape/middleware/auth/base_spec.rb +0 -1
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -2
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -2
- data/spec/grape/middleware/base_spec.rb +0 -2
- data/spec/grape/middleware/error_spec.rb +6 -1
- data/spec/grape/middleware/exception_spec.rb +0 -2
- data/spec/grape/middleware/formatter_spec.rb +0 -2
- data/spec/grape/middleware/globals_spec.rb +0 -2
- data/spec/grape/middleware/stack_spec.rb +0 -2
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -2
- data/spec/grape/middleware/versioner/header_spec.rb +18 -4
- data/spec/grape/middleware/versioner/param_spec.rb +0 -2
- data/spec/grape/middleware/versioner/path_spec.rb +0 -2
- data/spec/grape/middleware/versioner_spec.rb +0 -2
- data/spec/grape/named_api_spec.rb +0 -2
- data/spec/grape/parser_spec.rb +0 -2
- data/spec/grape/path_spec.rb +0 -2
- data/spec/grape/presenters/presenter_spec.rb +0 -2
- data/spec/grape/request_spec.rb +0 -2
- data/spec/grape/util/inheritable_setting_spec.rb +0 -1
- data/spec/grape/util/inheritable_values_spec.rb +0 -1
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -1
- data/spec/grape/util/stackable_values_spec.rb +0 -1
- 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 +0 -2
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -2
- data/spec/grape/validations/params_scope_spec.rb +315 -86
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -2
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
- data/spec/grape/validations/types/primitive_coercer_spec.rb +20 -5
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
- data/spec/grape/validations/types_spec.rb +28 -2
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -2
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -2
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -2
- data/spec/grape/validations/validators/coerce_spec.rb +0 -2
- data/spec/grape/validations/validators/default_spec.rb +0 -2
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -2
- data/spec/grape/validations/validators/except_values_spec.rb +0 -2
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -2
- data/spec/grape/validations/validators/presence_spec.rb +0 -2
- data/spec/grape/validations/validators/regexp_spec.rb +0 -2
- data/spec/grape/validations/validators/same_as_spec.rb +0 -2
- data/spec/grape/validations/validators/values_spec.rb +0 -2
- data/spec/grape/validations_spec.rb +50 -22
- data/spec/integration/multi_json/json_spec.rb +0 -2
- data/spec/integration/multi_xml/xml_spec.rb +0 -2
- data/spec/spec_helper.rb +9 -4
- metadata +30 -21
- data/spec/support/eager_load.rb +0 -19
@@ -1,13 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require_relative 'types/custom_type_collection_coercer'
|
6
|
-
require_relative 'types/multiple_type_coercer'
|
7
|
-
require_relative 'types/variant_collection_coercer'
|
8
|
-
require_relative 'types/json'
|
9
|
-
require_relative 'types/file'
|
10
|
-
require_relative 'types/invalid_value'
|
3
|
+
require 'grape/validations/types/json'
|
4
|
+
require 'grape/validations/types/file'
|
11
5
|
|
12
6
|
module Grape
|
13
7
|
module Validations
|
@@ -22,7 +16,8 @@ module Grape
|
|
22
16
|
# and {Grape::Dsl::Parameters#optional}. The main
|
23
17
|
# entry point for this process is {Types.build_coercer}.
|
24
18
|
module Types
|
25
|
-
|
19
|
+
module_function
|
20
|
+
|
26
21
|
PRIMITIVES = [
|
27
22
|
# Numerical
|
28
23
|
Integer,
|
@@ -44,33 +39,23 @@ module Grape
|
|
44
39
|
].freeze
|
45
40
|
|
46
41
|
# Types representing data structures.
|
47
|
-
STRUCTURES = [
|
48
|
-
Hash,
|
49
|
-
Array,
|
50
|
-
Set
|
51
|
-
].freeze
|
42
|
+
STRUCTURES = [Hash, Array, Set].freeze
|
52
43
|
|
53
|
-
# Special custom types provided by Grape.
|
54
44
|
SPECIAL = {
|
55
|
-
JSON => Json,
|
45
|
+
::JSON => Json,
|
56
46
|
Array[JSON] => JsonArray,
|
57
47
|
::File => File,
|
58
48
|
Rack::Multipart::UploadedFile => File
|
59
49
|
}.freeze
|
60
50
|
|
61
|
-
GROUPS = [
|
62
|
-
Array,
|
63
|
-
Hash,
|
64
|
-
JSON,
|
65
|
-
Array[JSON]
|
66
|
-
].freeze
|
51
|
+
GROUPS = [Array, Hash, JSON, Array[JSON]].freeze
|
67
52
|
|
68
53
|
# Is the given class a primitive type as recognized by Grape?
|
69
54
|
#
|
70
55
|
# @param type [Class] type to check
|
71
56
|
# @return [Boolean] whether or not the type is known by Grape as a valid
|
72
57
|
# type for a single value
|
73
|
-
def
|
58
|
+
def primitive?(type)
|
74
59
|
PRIMITIVES.include?(type)
|
75
60
|
end
|
76
61
|
|
@@ -80,7 +65,7 @@ module Grape
|
|
80
65
|
# @param type [Class] type to check
|
81
66
|
# @return [Boolean] whether or not the type is known by Grape as a valid
|
82
67
|
# data structure type
|
83
|
-
def
|
68
|
+
def structure?(type)
|
84
69
|
STRUCTURES.include?(type)
|
85
70
|
end
|
86
71
|
|
@@ -92,7 +77,7 @@ module Grape
|
|
92
77
|
# @param type [Array<Class>,Set<Class>] type (or type list!) to check
|
93
78
|
# @return [Boolean] +true+ if the given value will be treated as
|
94
79
|
# a list of types.
|
95
|
-
def
|
80
|
+
def multiple?(type)
|
96
81
|
(type.is_a?(Array) || type.is_a?(Set)) && type.size > 1
|
97
82
|
end
|
98
83
|
|
@@ -103,7 +88,7 @@ module Grape
|
|
103
88
|
#
|
104
89
|
# @param type [Class] type to check
|
105
90
|
# @return [Boolean] +true+ if special routines are available
|
106
|
-
def
|
91
|
+
def special?(type)
|
107
92
|
SPECIAL.key? type
|
108
93
|
end
|
109
94
|
|
@@ -112,7 +97,7 @@ module Grape
|
|
112
97
|
#
|
113
98
|
# @param type [Array<Class>,Class] type to check
|
114
99
|
# @return [Boolean] +true+ if the type is a supported group type
|
115
|
-
def
|
100
|
+
def group?(type)
|
116
101
|
GROUPS.include? type
|
117
102
|
end
|
118
103
|
|
@@ -121,7 +106,7 @@ module Grape
|
|
121
106
|
#
|
122
107
|
# @param type [Class] type to check
|
123
108
|
# @return [Boolean] whether or not the type can be used as a custom type
|
124
|
-
def
|
109
|
+
def custom?(type)
|
125
110
|
!primitive?(type) &&
|
126
111
|
!structure?(type) &&
|
127
112
|
!multiple?(type) &&
|
@@ -134,15 +119,98 @@ module Grape
|
|
134
119
|
# @param type [Array<Class>,Class] type to check
|
135
120
|
# @return [Boolean] true if +type+ is a collection of a type that implements
|
136
121
|
# its own +#parse+ method.
|
137
|
-
def
|
122
|
+
def collection_of_custom?(type)
|
138
123
|
(type.is_a?(Array) || type.is_a?(Set)) &&
|
139
124
|
type.length == 1 &&
|
140
125
|
(custom?(type.first) || special?(type.first))
|
141
126
|
end
|
142
127
|
|
143
|
-
def
|
128
|
+
def map_special(type)
|
144
129
|
SPECIAL.fetch(type, type)
|
145
130
|
end
|
131
|
+
|
132
|
+
# Chooses the best coercer for the given type. For example, if the type
|
133
|
+
# is Integer, it will return a coercer which will be able to coerce a value
|
134
|
+
# to the integer.
|
135
|
+
#
|
136
|
+
# There are a few very special coercers which might be returned.
|
137
|
+
#
|
138
|
+
# +Grape::Types::MultipleTypeCoercer+ is a coercer which is returned when
|
139
|
+
# the given type implies values in an array with different types.
|
140
|
+
# For example, +[Integer, String]+ allows integer and string values in
|
141
|
+
# an array.
|
142
|
+
#
|
143
|
+
# +Grape::Types::CustomTypeCoercer+ is a coercer which is returned when
|
144
|
+
# a method is specified by a user with +coerce_with+ option or the user
|
145
|
+
# specifies a custom type which implements requirments of
|
146
|
+
# +Grape::Types::CustomTypeCoercer+.
|
147
|
+
#
|
148
|
+
# +Grape::Types::CustomTypeCollectionCoercer+ is a very similar to the
|
149
|
+
# previous one, but it expects an array or set of values having a custom
|
150
|
+
# type implemented by the user.
|
151
|
+
#
|
152
|
+
# There is also a group of custom types implemented by Grape, check
|
153
|
+
# +Grape::Validations::Types::SPECIAL+ to get the full list.
|
154
|
+
#
|
155
|
+
# @param type [Class] the type to which input strings
|
156
|
+
# should be coerced
|
157
|
+
# @param method [Class,#call] the coercion method to use
|
158
|
+
# @return [Object] object to be used
|
159
|
+
# for coercion and type validation
|
160
|
+
def build_coercer(type, method: nil, strict: false)
|
161
|
+
cache_instance(type, method, strict) do
|
162
|
+
create_coercer_instance(type, method, strict)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def create_coercer_instance(type, method, strict)
|
167
|
+
# Maps a custom type provided by Grape, it doesn't map types wrapped by collections!!!
|
168
|
+
type = Types.map_special(type)
|
169
|
+
|
170
|
+
# Use a special coercer for multiply-typed parameters.
|
171
|
+
if Types.multiple?(type)
|
172
|
+
MultipleTypeCoercer.new(type, method)
|
173
|
+
|
174
|
+
# Use a special coercer for custom types and coercion methods.
|
175
|
+
elsif method || Types.custom?(type)
|
176
|
+
CustomTypeCoercer.new(type, method)
|
177
|
+
|
178
|
+
# Special coercer for collections of types that implement a parse method.
|
179
|
+
# CustomTypeCoercer (above) already handles such types when an explicit coercion
|
180
|
+
# method is supplied.
|
181
|
+
elsif Types.collection_of_custom?(type)
|
182
|
+
Types::CustomTypeCollectionCoercer.new(
|
183
|
+
Types.map_special(type.first), type.is_a?(Set)
|
184
|
+
)
|
185
|
+
else
|
186
|
+
DryTypeCoercer.coercer_instance_for(type, strict)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def cache_instance(type, method, strict, &_block)
|
191
|
+
key = cache_key(type, method, strict)
|
192
|
+
|
193
|
+
return @__cache[key] if @__cache.key?(key)
|
194
|
+
|
195
|
+
instance = yield
|
196
|
+
|
197
|
+
@__cache_write_lock.synchronize do
|
198
|
+
@__cache[key] = instance
|
199
|
+
end
|
200
|
+
|
201
|
+
instance
|
202
|
+
end
|
203
|
+
|
204
|
+
def cache_key(type, method, strict)
|
205
|
+
[type, method, strict].each_with_object(+'_') do |val, memo|
|
206
|
+
next if val.nil?
|
207
|
+
|
208
|
+
memo << '_' << val.to_s
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
instance_variable_set(:@__cache, {})
|
213
|
+
instance_variable_set(:@__cache_write_lock, Mutex.new)
|
146
214
|
end
|
147
215
|
end
|
148
216
|
end
|
File without changes
|
File without changes
|
@@ -93,3 +93,10 @@ module Grape
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
96
|
+
|
97
|
+
Grape::Validations::Base = Class.new(Grape::Validations::Validators::Base) do
|
98
|
+
def initialize(*)
|
99
|
+
super
|
100
|
+
warn '[DEPRECATION] `Grape::Validations::Base` is deprecated. Use `Grape::Validations::Validators::Base` instead.'
|
101
|
+
end
|
102
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/grape/validations.rb
CHANGED
@@ -1,30 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'grape/validations/attributes_iterator'
|
4
|
-
require 'grape/validations/single_attribute_iterator'
|
5
|
-
require 'grape/validations/multiple_attributes_iterator'
|
6
|
-
require 'grape/validations/params_scope'
|
7
|
-
require 'grape/validations/types'
|
8
|
-
|
9
3
|
module Grape
|
10
4
|
# Registry to store and locate known Validators.
|
11
5
|
module Validations
|
12
|
-
|
13
|
-
attr_accessor :validators
|
14
|
-
end
|
6
|
+
module_function
|
15
7
|
|
16
|
-
|
8
|
+
def validators
|
9
|
+
@validators ||= {}
|
10
|
+
end
|
17
11
|
|
18
12
|
# Register a new validator, so it can be used to validate parameters.
|
19
13
|
# @param short_name [String] all lower-case, no spaces
|
20
14
|
# @param klass [Class] the validator class. Should inherit from
|
21
15
|
# Validations::Base.
|
22
|
-
def
|
16
|
+
def register_validator(short_name, klass)
|
23
17
|
validators[short_name] = klass
|
24
18
|
end
|
25
19
|
|
26
|
-
def
|
20
|
+
def deregister_validator(short_name)
|
27
21
|
validators.delete(short_name)
|
28
22
|
end
|
23
|
+
|
24
|
+
# Find a validator and if not found will try to load it
|
25
|
+
def require_validator(short_name)
|
26
|
+
str_name = short_name.to_s
|
27
|
+
validators.fetch(str_name) do
|
28
|
+
Grape::Validations::Validators.const_get("#{str_name.camelize}Validator")
|
29
|
+
end
|
30
|
+
rescue NameError
|
31
|
+
raise Grape::Exceptions::UnknownValidator.new(short_name)
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
data/lib/grape/version.rb
CHANGED
data/lib/grape.rb
CHANGED
@@ -7,19 +7,22 @@ require 'rack/accept'
|
|
7
7
|
require 'rack/auth/basic'
|
8
8
|
require 'rack/auth/digest/md5'
|
9
9
|
require 'set'
|
10
|
+
require 'bigdecimal'
|
11
|
+
require 'date'
|
10
12
|
require 'active_support'
|
13
|
+
require 'active_support/concern'
|
11
14
|
require 'active_support/version'
|
12
15
|
require 'active_support/isolated_execution_state' if ActiveSupport::VERSION::MAJOR > 6
|
13
|
-
require 'active_support/core_ext/
|
14
|
-
require 'active_support/core_ext/object/blank'
|
16
|
+
require 'active_support/core_ext/array/conversions'
|
15
17
|
require 'active_support/core_ext/array/extract_options'
|
16
18
|
require 'active_support/core_ext/array/wrap'
|
17
|
-
require 'active_support/core_ext/
|
19
|
+
require 'active_support/core_ext/hash/conversions'
|
18
20
|
require 'active_support/core_ext/hash/deep_merge'
|
19
|
-
require 'active_support/core_ext/hash/reverse_merge'
|
20
21
|
require 'active_support/core_ext/hash/except'
|
22
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
23
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
21
24
|
require 'active_support/core_ext/hash/slice'
|
22
|
-
require 'active_support/core_ext/
|
25
|
+
require 'active_support/core_ext/object/blank'
|
23
26
|
require 'active_support/dependencies/autoload'
|
24
27
|
require 'active_support/notifications'
|
25
28
|
require 'i18n'
|
@@ -45,6 +48,7 @@ module Grape
|
|
45
48
|
autoload :Env, 'grape/util/env'
|
46
49
|
autoload :Json, 'grape/util/json'
|
47
50
|
autoload :Xml, 'grape/util/xml'
|
51
|
+
autoload :DryTypes
|
48
52
|
end
|
49
53
|
|
50
54
|
module Http
|
@@ -71,14 +75,17 @@ module Grape
|
|
71
75
|
autoload :UnknownParameter
|
72
76
|
autoload :InvalidWithOptionForRepresent
|
73
77
|
autoload :IncompatibleOptionValues
|
74
|
-
autoload :
|
75
|
-
autoload :
|
78
|
+
autoload :MissingGroupType
|
79
|
+
autoload :UnsupportedGroupType
|
76
80
|
autoload :InvalidMessageBody
|
77
81
|
autoload :InvalidAcceptHeader
|
78
82
|
autoload :InvalidVersionHeader
|
79
83
|
autoload :MethodNotAllowed
|
80
84
|
autoload :InvalidResponse
|
81
85
|
autoload :EmptyMessageBody
|
86
|
+
autoload :TooManyMultipartFiles
|
87
|
+
autoload :MissingGroupTypeError, 'grape/exceptions/missing_group_type'
|
88
|
+
autoload :UnsupportedGroupTypeError, 'grape/exceptions/unsupported_group_type'
|
82
89
|
end
|
83
90
|
end
|
84
91
|
|
@@ -218,6 +225,58 @@ module Grape
|
|
218
225
|
autoload :StreamResponse
|
219
226
|
end
|
220
227
|
end
|
228
|
+
|
229
|
+
module Validations
|
230
|
+
extend ::ActiveSupport::Autoload
|
231
|
+
|
232
|
+
eager_autoload do
|
233
|
+
autoload :AttributesIterator
|
234
|
+
autoload :MultipleAttributesIterator
|
235
|
+
autoload :SingleAttributeIterator
|
236
|
+
autoload :Types
|
237
|
+
autoload :ParamsScope
|
238
|
+
autoload :ValidatorFactory
|
239
|
+
autoload :Base, 'grape/validations/validators/base'
|
240
|
+
end
|
241
|
+
|
242
|
+
module Types
|
243
|
+
extend ::ActiveSupport::Autoload
|
244
|
+
|
245
|
+
eager_autoload do
|
246
|
+
autoload :InvalidValue
|
247
|
+
autoload :DryTypeCoercer
|
248
|
+
autoload :ArrayCoercer
|
249
|
+
autoload :SetCoercer
|
250
|
+
autoload :PrimitiveCoercer
|
251
|
+
autoload :CustomTypeCoercer
|
252
|
+
autoload :CustomTypeCollectionCoercer
|
253
|
+
autoload :MultipleTypeCoercer
|
254
|
+
autoload :VariantCollectionCoercer
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
module Validators
|
259
|
+
extend ::ActiveSupport::Autoload
|
260
|
+
|
261
|
+
eager_autoload do
|
262
|
+
autoload :Base
|
263
|
+
autoload :MultipleParamsBase
|
264
|
+
autoload :AllOrNoneOfValidator
|
265
|
+
autoload :AllowBlankValidator
|
266
|
+
autoload :AsValidator
|
267
|
+
autoload :AtLeastOneOfValidator
|
268
|
+
autoload :CoerceValidator
|
269
|
+
autoload :DefaultValidator
|
270
|
+
autoload :ExactlyOneOfValidator
|
271
|
+
autoload :ExceptValuesValidator
|
272
|
+
autoload :MutualExclusionValidator
|
273
|
+
autoload :PresenceValidator
|
274
|
+
autoload :RegexpValidator
|
275
|
+
autoload :SameAsValidator
|
276
|
+
autoload :ValuesValidator
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
221
280
|
end
|
222
281
|
|
223
282
|
require 'grape/config'
|
@@ -227,25 +286,4 @@ require 'grape/util/lazy_value'
|
|
227
286
|
require 'grape/util/lazy_block'
|
228
287
|
require 'grape/util/endpoint_configuration'
|
229
288
|
|
230
|
-
require 'grape/validations/validators/base'
|
231
|
-
require 'grape/validations/attributes_iterator'
|
232
|
-
require 'grape/validations/single_attribute_iterator'
|
233
|
-
require 'grape/validations/multiple_attributes_iterator'
|
234
|
-
require 'grape/validations/validators/allow_blank'
|
235
|
-
require 'grape/validations/validators/as'
|
236
|
-
require 'grape/validations/validators/at_least_one_of'
|
237
|
-
require 'grape/validations/validators/coerce'
|
238
|
-
require 'grape/validations/validators/default'
|
239
|
-
require 'grape/validations/validators/exactly_one_of'
|
240
|
-
require 'grape/validations/validators/mutual_exclusion'
|
241
|
-
require 'grape/validations/validators/presence'
|
242
|
-
require 'grape/validations/validators/regexp'
|
243
|
-
require 'grape/validations/validators/same_as'
|
244
|
-
require 'grape/validations/validators/values'
|
245
|
-
require 'grape/validations/validators/except_values'
|
246
|
-
require 'grape/validations/params_scope'
|
247
|
-
require 'grape/validations/validators/all_or_none'
|
248
|
-
require 'grape/validations/types'
|
249
|
-
require 'grape/validations/validator_factory'
|
250
|
-
|
251
289
|
require 'grape/version'
|
@@ -1,8 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
3
|
describe Grape::Validations do
|
4
|
+
context 'deprecated Grape::Validations::Base' do
|
5
|
+
subject do
|
6
|
+
Class.new(Grape::API) do
|
7
|
+
params do
|
8
|
+
requires :text, validator_with_old_base: true
|
9
|
+
end
|
10
|
+
get do
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:validator_with_old_base) do
|
16
|
+
Class.new(Grape::Validations::Base) do
|
17
|
+
def validate_param!(_attr_name, _params)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
before do
|
24
|
+
described_class.register_validator('validator_with_old_base', validator_with_old_base)
|
25
|
+
allow(Warning).to receive(:warn)
|
26
|
+
end
|
27
|
+
|
28
|
+
after do
|
29
|
+
described_class.deregister_validator('validator_with_old_base')
|
30
|
+
end
|
31
|
+
|
32
|
+
def app
|
33
|
+
subject
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'puts a deprecation warning' do
|
37
|
+
expect(Warning).to receive(:warn) do |message|
|
38
|
+
expect(message).to include('`Grape::Validations::Base` is deprecated')
|
39
|
+
end
|
40
|
+
|
41
|
+
get '/'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
6
45
|
context 'using a custom length validator' do
|
7
46
|
subject do
|
8
47
|
Class.new(Grape::API) do
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Grape::API do
|
6
|
+
subject { Class.new(described_class) }
|
7
|
+
|
8
|
+
let(:app) { subject }
|
9
|
+
|
10
|
+
context 'an endpoint with documentation' do
|
11
|
+
it 'documents parameters' do
|
12
|
+
subject.params do
|
13
|
+
requires 'price', type: Float, desc: 'Sales price'
|
14
|
+
end
|
15
|
+
subject.get '/'
|
16
|
+
|
17
|
+
expect(subject.routes.first.params['price']).to eq(required: true,
|
18
|
+
type: 'Float',
|
19
|
+
desc: 'Sales price')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'allows documentation with a hash' do
|
23
|
+
documentation = { example: 'Joe' }
|
24
|
+
|
25
|
+
subject.params do
|
26
|
+
requires 'first_name', documentation: documentation
|
27
|
+
end
|
28
|
+
subject.get '/'
|
29
|
+
|
30
|
+
expect(subject.routes.first.params['first_name'][:documentation]).to eq(documentation)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'an endpoint without documentation' do
|
35
|
+
before do
|
36
|
+
subject.do_not_document!
|
37
|
+
|
38
|
+
subject.params do
|
39
|
+
requires :city, type: String, desc: 'Should be ignored'
|
40
|
+
optional :postal_code, type: Integer
|
41
|
+
end
|
42
|
+
subject.post '/' do
|
43
|
+
declared(params).to_json
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'does not document parameters for the endpoint' do
|
48
|
+
expect(subject.routes.first.params).to eq({})
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'still declares params internally' do
|
52
|
+
data = { city: 'Berlin', postal_code: 10_115 }
|
53
|
+
|
54
|
+
post '/', data
|
55
|
+
|
56
|
+
expect(last_response.body).to eq(data.to_json)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|