grape 1.3.3 → 1.6.2
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 +111 -2
- data/CONTRIBUTING.md +2 -1
- data/README.md +135 -23
- data/UPGRADING.md +237 -46
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +34 -42
- data/lib/grape/api.rb +21 -16
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +1 -1
- data/lib/grape/dsl/desc.rb +3 -5
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +8 -5
- data/lib/grape/dsl/inside_route.rb +72 -53
- data/lib/grape/dsl/middleware.rb +4 -4
- data/lib/grape/dsl/parameters.rb +11 -7
- data/lib/grape/dsl/request_response.rb +9 -6
- data/lib/grape/dsl/routing.rb +8 -9
- data/lib/grape/dsl/settings.rb +5 -5
- data/lib/grape/dsl/validations.rb +18 -1
- data/lib/grape/eager_load.rb +1 -1
- data/lib/grape/endpoint.rb +29 -42
- data/lib/grape/error_formatter/json.rb +2 -6
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/validation.rb +2 -3
- data/lib/grape/exceptions/validation_errors.rb +1 -1
- 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 +1 -1
- data/lib/grape/middleware/auth/base.rb +3 -3
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +6 -3
- data/lib/grape/middleware/error.rb +11 -13
- data/lib/grape/middleware/formatter.rb +7 -7
- data/lib/grape/middleware/stack.rb +10 -3
- 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 +4 -1
- data/lib/grape/router/attribute_translator.rb +3 -3
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +31 -30
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
- data/lib/grape/util/base_inheritable.rb +2 -2
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/lazy_value.rb +4 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_iterator.rb +8 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +97 -62
- data/lib/grape/validations/single_attribute_iterator.rb +1 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +16 -3
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +4 -5
- data/lib/grape/validations/types.rb +1 -4
- data/lib/grape/validations/validator_factory.rb +1 -1
- data/lib/grape/validations/validators/all_or_none.rb +8 -5
- data/lib/grape/validations/validators/allow_blank.rb +9 -7
- data/lib/grape/validations/validators/as.rb +6 -8
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
- data/lib/grape/validations/validators/base.rb +74 -69
- data/lib/grape/validations/validators/coerce.rb +63 -76
- data/lib/grape/validations/validators/default.rb +36 -34
- data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
- data/lib/grape/validations/validators/except_values.rb +13 -11
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -19
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
- data/lib/grape/validations/validators/presence.rb +7 -4
- data/lib/grape/validations/validators/regexp.rb +8 -5
- data/lib/grape/validations/validators/same_as.rb +18 -15
- data/lib/grape/validations/validators/values.rb +61 -56
- data/lib/grape/validations.rb +6 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +7 -3
- data/spec/grape/api/custom_validations_spec.rb +77 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +25 -19
- data/spec/grape/api_spec.rb +576 -211
- data/spec/grape/dsl/callbacks_spec.rb +2 -1
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +185 -34
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +2 -1
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +10 -7
- data/spec/grape/endpoint/declared_spec.rb +848 -0
- data/spec/grape/endpoint_spec.rb +77 -589
- data/spec/grape/entity_spec.rb +29 -23
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +13 -9
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
- data/spec/grape/middleware/auth/strategies_spec.rb +61 -21
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +3 -3
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +28 -7
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +15 -12
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +14 -3
- data/spec/grape/validations/params_scope_spec.rb +72 -10
- data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -6
- data/spec/grape/validations/types/primitive_coercer_spec.rb +63 -7
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +248 -33
- data/spec/grape/validations/validators/default_spec.rb +121 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +4 -3
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +183 -178
- data/spec/grape/validations_spec.rb +342 -29
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +32 -29
- data/spec/spec_helper.rb +12 -12
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- data/spec/support/chunks.rb +14 -0
- data/spec/support/versioned_helpers.rb +4 -6
- metadata +110 -102
@@ -4,12 +4,15 @@ require 'grape/validations/validators/multiple_params_base'
|
|
4
4
|
|
5
5
|
module Grape
|
6
6
|
module Validations
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
module Validators
|
8
|
+
class ExactlyOneOfValidator < MultipleParamsBase
|
9
|
+
def validate_params!(params)
|
10
|
+
keys = keys_in_common(params)
|
11
|
+
return if keys.length == 1
|
12
|
+
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:exactly_one)) if keys.length.zero?
|
13
|
+
|
14
|
+
raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
|
15
|
+
end
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -2,20 +2,22 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
module Validators
|
6
|
+
class ExceptValuesValidator < Base
|
7
|
+
def initialize(attrs, options, required, scope, **opts)
|
8
|
+
@except = options.is_a?(Hash) ? options[:value] : options
|
9
|
+
super
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def validate_param!(attr_name, params)
|
13
|
+
return unless params.respond_to?(:key?) && params.key?(attr_name)
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
excepts = @except.is_a?(Proc) ? @except.call : @except
|
16
|
+
return if excepts.nil?
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
|
19
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:except_values)) if param_array.any? { |param| excepts.include?(param) }
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -2,31 +2,36 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
module Validators
|
6
|
+
class MultipleParamsBase < Base
|
7
|
+
def validate!(params)
|
8
|
+
attributes = MultipleAttributesIterator.new(self, @scope, params)
|
9
|
+
array_errors = []
|
10
|
+
|
11
|
+
attributes.each do |resource_params, skip_value|
|
12
|
+
next if skip_value
|
13
|
+
|
14
|
+
begin
|
15
|
+
validate_params!(resource_params)
|
16
|
+
rescue Grape::Exceptions::Validation => e
|
17
|
+
array_errors << e
|
18
|
+
end
|
15
19
|
end
|
20
|
+
|
21
|
+
raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors.any?
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
end
|
24
|
+
private
|
20
25
|
|
21
|
-
|
26
|
+
def keys_in_common(resource_params)
|
27
|
+
return [] unless resource_params.is_a?(Hash)
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
all_keys & resource_params.keys.map! { |attr| @scope.full_name(attr) }
|
26
|
-
end
|
29
|
+
all_keys & resource_params.keys.map! { |attr| @scope.full_name(attr) }
|
30
|
+
end
|
27
31
|
|
28
|
-
|
29
|
-
|
32
|
+
def all_keys
|
33
|
+
attrs.map { |attr| @scope.full_name(attr) }
|
34
|
+
end
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
@@ -4,11 +4,14 @@ require 'grape/validations/validators/multiple_params_base'
|
|
4
4
|
|
5
5
|
module Grape
|
6
6
|
module Validations
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
module Validators
|
8
|
+
class MutualExclusionValidator < MultipleParamsBase
|
9
|
+
def validate_params!(params)
|
10
|
+
keys = keys_in_common(params)
|
11
|
+
return if keys.length <= 1
|
12
|
+
|
13
|
+
raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
|
14
|
+
end
|
12
15
|
end
|
13
16
|
end
|
14
17
|
end
|
@@ -2,10 +2,13 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
module Validators
|
6
|
+
class PresenceValidator < Base
|
7
|
+
def validate_param!(attr_name, params)
|
8
|
+
return if params.respond_to?(:key?) && params.key?(attr_name)
|
9
|
+
|
10
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:presence))
|
11
|
+
end
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
module Validators
|
6
|
+
class RegexpValidator < Base
|
7
|
+
def validate_param!(attr_name, params)
|
8
|
+
return unless params.respond_to?(:key?) && params.key?(attr_name)
|
9
|
+
return if Array.wrap(params[attr_name]).all? { |param| param.nil? || param.to_s.match?((options_key?(:value) ? @option[:value] : @option)) }
|
10
|
+
|
11
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:regexp))
|
12
|
+
end
|
10
13
|
end
|
11
14
|
end
|
12
15
|
end
|
@@ -2,23 +2,26 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
module Validators
|
6
|
+
class SameAsValidator < Base
|
7
|
+
def validate_param!(attr_name, params)
|
8
|
+
confirmation = options_key?(:value) ? @option[:value] : @option
|
9
|
+
return if params[attr_name] == params[confirmation]
|
10
|
+
|
11
|
+
raise Grape::Exceptions::Validation.new(
|
12
|
+
params: [@scope.full_name(attr_name)],
|
13
|
+
message: build_message
|
14
|
+
)
|
15
|
+
end
|
14
16
|
|
15
|
-
|
17
|
+
private
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
def build_message
|
20
|
+
if options_key?(:message)
|
21
|
+
@option[:message]
|
22
|
+
else
|
23
|
+
format I18n.t(:same_as, scope: 'grape.errors.messages'), parameter: @option
|
24
|
+
end
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -2,81 +2,86 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
5
|
+
module Validators
|
6
|
+
class ValuesValidator < Base
|
7
|
+
def initialize(attrs, options, required, scope, **opts)
|
8
|
+
if options.is_a?(Hash)
|
9
|
+
@excepts = options[:except]
|
10
|
+
@values = options[:value]
|
11
|
+
@proc = options[:proc]
|
12
|
+
|
13
|
+
warn '[DEPRECATION] The values validator except option is deprecated. ' \
|
14
|
+
'Use the except validator instead.' if @excepts
|
15
|
+
|
16
|
+
raise ArgumentError, 'proc must be a Proc' if @proc && !@proc.is_a?(Proc)
|
17
|
+
|
18
|
+
warn '[DEPRECATION] The values validator proc option is deprecated. ' \
|
19
|
+
'The lambda expression can now be assigned directly to values.' if @proc
|
20
|
+
else
|
21
|
+
@excepts = nil
|
22
|
+
@values = nil
|
23
|
+
@proc = nil
|
24
|
+
@values = options
|
25
|
+
end
|
26
|
+
super
|
23
27
|
end
|
24
|
-
super
|
25
|
-
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
def validate_param!(attr_name, params)
|
30
|
+
return unless params.is_a?(Hash)
|
29
31
|
|
30
|
-
|
32
|
+
val = params[attr_name]
|
31
33
|
|
32
|
-
|
34
|
+
return if val.nil? && !required_for_root_scope?
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
# don't forget that +false.blank?+ is true
|
37
|
+
return if val != false && val.blank? && @allow_blank
|
36
38
|
|
37
|
-
|
39
|
+
param_array = val.nil? ? [nil] : Array.wrap(val)
|
38
40
|
|
39
|
-
|
41
|
+
raise validation_exception(attr_name, except_message) \
|
40
42
|
unless check_excepts(param_array)
|
41
43
|
|
42
|
-
|
44
|
+
raise validation_exception(attr_name, message(:values)) \
|
43
45
|
unless check_values(param_array, attr_name)
|
44
46
|
|
45
|
-
|
47
|
+
raise validation_exception(attr_name, message(:values)) \
|
46
48
|
if @proc && !param_array.all? { |param| @proc.call(param) }
|
47
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
48
52
|
|
49
|
-
|
53
|
+
def check_values(param_array, attr_name)
|
54
|
+
values = @values.is_a?(Proc) && @values.arity.zero? ? @values.call : @values
|
55
|
+
return true if values.nil?
|
50
56
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
return false
|
57
|
+
begin
|
58
|
+
return param_array.all? { |param| values.call(param) } if values.is_a? Proc
|
59
|
+
rescue StandardError => e
|
60
|
+
warn "Error '#{e}' raised while validating attribute '#{attr_name}'"
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
param_array.all? { |param| values.include?(param) }
|
59
64
|
end
|
60
|
-
param_array.all? { |param| values.include?(param) }
|
61
|
-
end
|
62
65
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
param_array.none? { |param| excepts.include?(param) }
|
67
|
-
end
|
66
|
+
def check_excepts(param_array)
|
67
|
+
excepts = @excepts.is_a?(Proc) ? @excepts.call : @excepts
|
68
|
+
return true if excepts.nil?
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
options_key?(:except_message) ? options[:except_message] : message(:except_values)
|
72
|
-
end
|
70
|
+
param_array.none? { |param| excepts.include?(param) }
|
71
|
+
end
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
def except_message
|
74
|
+
options = instance_variable_get(:@option)
|
75
|
+
options_key?(:except_message) ? options[:except_message] : message(:except_values)
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
78
|
+
def required_for_root_scope?
|
79
|
+
@required && @scope.root?
|
80
|
+
end
|
81
|
+
|
82
|
+
def validation_exception(attr_name, message)
|
83
|
+
Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
|
84
|
+
end
|
80
85
|
end
|
81
86
|
end
|
82
87
|
end
|
data/lib/grape/validations.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
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
|
+
|
3
9
|
module Grape
|
4
10
|
# Registry to store and locate known Validators.
|
5
11
|
module Validations
|
data/lib/grape/version.rb
CHANGED
data/lib/grape.rb
CHANGED
@@ -7,11 +7,14 @@ require 'rack/accept'
|
|
7
7
|
require 'rack/auth/basic'
|
8
8
|
require 'rack/auth/digest/md5'
|
9
9
|
require 'set'
|
10
|
+
require 'active_support'
|
10
11
|
require 'active_support/version'
|
12
|
+
require 'active_support/isolated_execution_state' if ActiveSupport::VERSION::MAJOR > 6
|
11
13
|
require 'active_support/core_ext/hash/indifferent_access'
|
12
14
|
require 'active_support/core_ext/object/blank'
|
13
15
|
require 'active_support/core_ext/array/extract_options'
|
14
16
|
require 'active_support/core_ext/array/wrap'
|
17
|
+
require 'active_support/core_ext/array/conversions'
|
15
18
|
require 'active_support/core_ext/hash/deep_merge'
|
16
19
|
require 'active_support/core_ext/hash/reverse_merge'
|
17
20
|
require 'active_support/core_ext/hash/except'
|
@@ -21,7 +24,7 @@ require 'active_support/dependencies/autoload'
|
|
21
24
|
require 'active_support/notifications'
|
22
25
|
require 'i18n'
|
23
26
|
|
24
|
-
I18n.load_path << File.expand_path('
|
27
|
+
I18n.load_path << File.expand_path('grape/locale/en.yml', __dir__)
|
25
28
|
|
26
29
|
module Grape
|
27
30
|
extend ::ActiveSupport::Autoload
|
@@ -75,6 +78,7 @@ module Grape
|
|
75
78
|
autoload :InvalidVersionHeader
|
76
79
|
autoload :MethodNotAllowed
|
77
80
|
autoload :InvalidResponse
|
81
|
+
autoload :EmptyMessageBody
|
78
82
|
end
|
79
83
|
end
|
80
84
|
|
@@ -206,12 +210,12 @@ module Grape
|
|
206
210
|
end
|
207
211
|
end
|
208
212
|
|
209
|
-
module
|
213
|
+
module ServeStream
|
210
214
|
extend ::ActiveSupport::Autoload
|
211
215
|
eager_autoload do
|
212
|
-
autoload :FileResponse
|
213
216
|
autoload :FileBody
|
214
217
|
autoload :SendfileResponse
|
218
|
+
autoload :StreamResponse
|
215
219
|
end
|
216
220
|
end
|
217
221
|
end
|
@@ -4,17 +4,6 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Grape::Validations do
|
6
6
|
context 'using a custom length validator' do
|
7
|
-
before do
|
8
|
-
module CustomValidationsSpec
|
9
|
-
class DefaultLength < Grape::Validations::Base
|
10
|
-
def validate_param!(attr_name, params)
|
11
|
-
@option = params[:max].to_i if params.key?(:max)
|
12
|
-
return if params[attr_name].length <= @option
|
13
|
-
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
7
|
subject do
|
19
8
|
Class.new(Grape::API) do
|
20
9
|
params do
|
@@ -26,6 +15,25 @@ describe Grape::Validations do
|
|
26
15
|
end
|
27
16
|
end
|
28
17
|
|
18
|
+
let(:default_length_validator) do
|
19
|
+
Class.new(Grape::Validations::Validators::Base) do
|
20
|
+
def validate_param!(attr_name, params)
|
21
|
+
@option = params[:max].to_i if params.key?(:max)
|
22
|
+
return if params[attr_name].length <= @option
|
23
|
+
|
24
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
before do
|
30
|
+
described_class.register_validator('default_length', default_length_validator)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
described_class.deregister_validator('default_length')
|
35
|
+
end
|
36
|
+
|
29
37
|
def app
|
30
38
|
subject
|
31
39
|
end
|
@@ -35,11 +43,13 @@ describe Grape::Validations do
|
|
35
43
|
expect(last_response.status).to eq 200
|
36
44
|
expect(last_response.body).to eq 'bacon'
|
37
45
|
end
|
46
|
+
|
38
47
|
it 'over 140 characters' do
|
39
48
|
get '/', text: 'a' * 141
|
40
49
|
expect(last_response.status).to eq 400
|
41
50
|
expect(last_response.body).to eq 'text must be at the most 140 characters long'
|
42
51
|
end
|
52
|
+
|
43
53
|
it 'specified in the query string' do
|
44
54
|
get '/', text: 'a' * 141, max: 141
|
45
55
|
expect(last_response.status).to eq 200
|
@@ -48,15 +58,6 @@ describe Grape::Validations do
|
|
48
58
|
end
|
49
59
|
|
50
60
|
context 'using a custom body-only validator' do
|
51
|
-
before do
|
52
|
-
module CustomValidationsSpec
|
53
|
-
class InBody < Grape::Validations::PresenceValidator
|
54
|
-
def validate(request)
|
55
|
-
validate!(request.env['api.request.body'])
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
61
|
subject do
|
61
62
|
Class.new(Grape::API) do
|
62
63
|
params do
|
@@ -68,6 +69,22 @@ describe Grape::Validations do
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
72
|
+
let(:in_body_validator) do
|
73
|
+
Class.new(Grape::Validations::Validators::PresenceValidator) do
|
74
|
+
def validate(request)
|
75
|
+
validate!(request.env['api.request.body'])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
before do
|
81
|
+
described_class.register_validator('in_body', in_body_validator)
|
82
|
+
end
|
83
|
+
|
84
|
+
after do
|
85
|
+
described_class.deregister_validator('in_body')
|
86
|
+
end
|
87
|
+
|
71
88
|
def app
|
72
89
|
subject
|
73
90
|
end
|
@@ -77,6 +94,7 @@ describe Grape::Validations do
|
|
77
94
|
expect(last_response.status).to eq 200
|
78
95
|
expect(last_response.body).to eq 'bacon'
|
79
96
|
end
|
97
|
+
|
80
98
|
it 'ignores field in query' do
|
81
99
|
get '/', nil, text: 'abc'
|
82
100
|
expect(last_response.status).to eq 400
|
@@ -85,15 +103,6 @@ describe Grape::Validations do
|
|
85
103
|
end
|
86
104
|
|
87
105
|
context 'using a custom validator with message_key' do
|
88
|
-
before do
|
89
|
-
module CustomValidationsSpec
|
90
|
-
class WithMessageKey < Grape::Validations::PresenceValidator
|
91
|
-
def validate_param!(attr_name, _params)
|
92
|
-
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: :presence)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
106
|
subject do
|
98
107
|
Class.new(Grape::API) do
|
99
108
|
params do
|
@@ -105,6 +114,22 @@ describe Grape::Validations do
|
|
105
114
|
end
|
106
115
|
end
|
107
116
|
|
117
|
+
let(:message_key_validator) do
|
118
|
+
Class.new(Grape::Validations::Validators::PresenceValidator) do
|
119
|
+
def validate_param!(attr_name, _params)
|
120
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: :presence)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
before do
|
126
|
+
described_class.register_validator('with_message_key', message_key_validator)
|
127
|
+
end
|
128
|
+
|
129
|
+
after do
|
130
|
+
described_class.deregister_validator('with_message_key')
|
131
|
+
end
|
132
|
+
|
108
133
|
def app
|
109
134
|
subject
|
110
135
|
end
|
@@ -117,22 +142,6 @@ describe Grape::Validations do
|
|
117
142
|
end
|
118
143
|
|
119
144
|
context 'using a custom request/param validator' do
|
120
|
-
before do
|
121
|
-
module CustomValidationsSpec
|
122
|
-
class Admin < Grape::Validations::Base
|
123
|
-
def validate(request)
|
124
|
-
# return if the param we are checking was not in request
|
125
|
-
# @attrs is a list containing the attribute we are currently validating
|
126
|
-
return unless request.params.key? @attrs.first
|
127
|
-
# check if admin flag is set to true
|
128
|
-
return unless @option
|
129
|
-
# check if user is admin or not
|
130
|
-
# as an example get a token from request and check if it's admin or not
|
131
|
-
raise Grape::Exceptions::Validation.new(params: @attrs, message: 'Can not set Admin only field.') unless request.headers['X-Access-Token'] == 'admin'
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
145
|
subject do
|
137
146
|
Class.new(Grape::API) do
|
138
147
|
params do
|
@@ -146,6 +155,29 @@ describe Grape::Validations do
|
|
146
155
|
end
|
147
156
|
end
|
148
157
|
|
158
|
+
let(:admin_validator) do
|
159
|
+
Class.new(Grape::Validations::Validators::Base) do
|
160
|
+
def validate(request)
|
161
|
+
# return if the param we are checking was not in request
|
162
|
+
# @attrs is a list containing the attribute we are currently validating
|
163
|
+
return unless request.params.key? @attrs.first
|
164
|
+
# check if admin flag is set to true
|
165
|
+
return unless @option
|
166
|
+
# check if user is admin or not
|
167
|
+
# as an example get a token from request and check if it's admin or not
|
168
|
+
raise Grape::Exceptions::Validation.new(params: @attrs, message: 'Can not set Admin only field.') unless request.headers['X-Access-Token'] == 'admin'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
before do
|
174
|
+
described_class.register_validator('admin', admin_validator)
|
175
|
+
end
|
176
|
+
|
177
|
+
after do
|
178
|
+
described_class.deregister_validator('admin')
|
179
|
+
end
|
180
|
+
|
149
181
|
def app
|
150
182
|
subject
|
151
183
|
end
|
@@ -41,18 +41,18 @@ describe Grape::API do
|
|
41
41
|
|
42
42
|
it 'works for unspecified format' do
|
43
43
|
get '/users'
|
44
|
-
expect(last_response.status).to
|
44
|
+
expect(last_response.status).to be 200
|
45
45
|
expect(last_response.content_type).to eql 'application/json'
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'works for specified format' do
|
49
49
|
get '/users.json'
|
50
|
-
expect(last_response.status).to
|
50
|
+
expect(last_response.status).to be 200
|
51
51
|
expect(last_response.content_type).to eql 'application/json'
|
52
52
|
end
|
53
53
|
|
54
54
|
it "doesn't work for format different than specified" do
|
55
55
|
get '/users.txt'
|
56
|
-
expect(last_response.status).to
|
56
|
+
expect(last_response.status).to be 404
|
57
57
|
end
|
58
58
|
end
|
@@ -31,8 +31,9 @@ describe Grape::API::Instance do
|
|
31
31
|
|
32
32
|
context 'Params endpoint type' do
|
33
33
|
subject { DefinesBooleanInstanceSpec::API.new.router.map['POST'].first.options[:params]['message'][:type] }
|
34
|
+
|
34
35
|
it 'params type is a boolean' do
|
35
|
-
|
36
|
+
expect(subject).to eq 'Grape::API::Boolean'
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|