grape 1.1.0 → 1.5.3
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 +278 -44
- data/LICENSE +1 -1
- data/README.md +514 -69
- data/UPGRADING.md +424 -17
- data/grape.gemspec +13 -2
- data/lib/grape.rb +104 -71
- data/lib/grape/api.rb +138 -175
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +283 -0
- data/lib/grape/config.rb +34 -0
- data/lib/grape/content_types.rb +34 -0
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/api.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +22 -0
- data/lib/grape/dsl/configuration.rb +2 -0
- data/lib/grape/dsl/desc.rb +41 -7
- data/lib/grape/dsl/headers.rb +2 -0
- data/lib/grape/dsl/helpers.rb +5 -2
- data/lib/grape/dsl/inside_route.rb +92 -49
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +9 -0
- data/lib/grape/dsl/parameters.rb +25 -14
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +17 -10
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +24 -4
- data/lib/grape/eager_load.rb +20 -0
- data/lib/grape/endpoint.rb +59 -35
- data/lib/grape/error_formatter.rb +4 -2
- data/lib/grape/error_formatter/base.rb +2 -0
- data/lib/grape/error_formatter/json.rb +2 -0
- data/lib/grape/error_formatter/txt.rb +2 -0
- data/lib/grape/error_formatter/xml.rb +2 -0
- data/lib/grape/exceptions/base.rb +20 -14
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
- data/lib/grape/exceptions/invalid_formatter.rb +2 -0
- data/lib/grape/exceptions/invalid_message_body.rb +2 -0
- data/lib/grape/exceptions/invalid_response.rb +11 -0
- data/lib/grape/exceptions/invalid_version_header.rb +2 -0
- data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
- data/lib/grape/exceptions/method_not_allowed.rb +2 -0
- data/lib/grape/exceptions/missing_group_type.rb +2 -0
- data/lib/grape/exceptions/missing_mime_type.rb +2 -0
- data/lib/grape/exceptions/missing_option.rb +2 -0
- data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
- data/lib/grape/exceptions/unknown_options.rb +2 -0
- data/lib/grape/exceptions/unknown_parameter.rb +2 -0
- data/lib/grape/exceptions/unknown_validator.rb +2 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
- data/lib/grape/exceptions/validation.rb +4 -2
- data/lib/grape/exceptions/validation_array_errors.rb +2 -0
- data/lib/grape/exceptions/validation_errors.rb +16 -13
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
- data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
- data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
- data/lib/grape/extensions/hash.rb +2 -0
- data/lib/grape/extensions/hashie/mash.rb +2 -0
- data/lib/grape/formatter.rb +5 -3
- data/lib/grape/formatter/json.rb +2 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -0
- data/lib/grape/formatter/txt.rb +2 -0
- data/lib/grape/formatter/xml.rb +2 -0
- data/lib/grape/http/headers.rb +50 -18
- data/lib/grape/locale/en.yml +3 -1
- data/lib/grape/middleware/auth/base.rb +7 -7
- data/lib/grape/middleware/auth/dsl.rb +2 -0
- data/lib/grape/middleware/auth/strategies.rb +2 -0
- data/lib/grape/middleware/auth/strategy_info.rb +2 -0
- data/lib/grape/middleware/base.rb +10 -7
- data/lib/grape/middleware/error.rb +21 -16
- data/lib/grape/middleware/filter.rb +2 -0
- data/lib/grape/middleware/formatter.rb +8 -6
- data/lib/grape/middleware/globals.rb +2 -0
- data/lib/grape/middleware/helpers.rb +12 -0
- data/lib/grape/middleware/stack.rb +13 -3
- data/lib/grape/middleware/versioner.rb +2 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
- data/lib/grape/middleware/versioner/header.rb +10 -8
- data/lib/grape/middleware/versioner/param.rb +3 -1
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
- data/lib/grape/middleware/versioner/path.rb +3 -1
- data/lib/grape/namespace.rb +14 -2
- data/lib/grape/parser.rb +4 -2
- data/lib/grape/parser/json.rb +3 -1
- data/lib/grape/parser/xml.rb +3 -1
- data/lib/grape/path.rb +15 -3
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +19 -10
- data/lib/grape/router.rb +30 -29
- data/lib/grape/router/attribute_translator.rb +41 -8
- data/lib/grape/router/pattern.rb +20 -16
- data/lib/grape/router/route.rb +14 -28
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
- data/lib/grape/util/base_inheritable.rb +43 -0
- data/lib/grape/util/cache.rb +20 -0
- data/lib/grape/util/endpoint_configuration.rb +8 -0
- data/lib/grape/util/env.rb +19 -17
- data/lib/grape/util/inheritable_setting.rb +2 -0
- data/lib/grape/util/inheritable_values.rb +7 -25
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_block.rb +27 -0
- data/lib/grape/util/lazy_object.rb +43 -0
- data/lib/grape/util/lazy_value.rb +98 -0
- data/lib/grape/util/registrable.rb +2 -0
- data/lib/grape/util/reverse_stackable_values.rb +10 -35
- data/lib/grape/util/stackable_values.rb +21 -34
- data/lib/grape/util/strict_hash_configuration.rb +2 -0
- data/lib/grape/util/xml.rb +2 -0
- data/lib/grape/validations.rb +2 -0
- data/lib/grape/validations/attributes_iterator.rb +16 -6
- data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
- data/lib/grape/validations/params_scope.rb +51 -30
- data/lib/grape/validations/single_attribute_iterator.rb +24 -0
- data/lib/grape/validations/types.rb +13 -38
- data/lib/grape/validations/types/array_coercer.rb +65 -0
- data/lib/grape/validations/types/build_coercer.rb +47 -49
- data/lib/grape/validations/types/custom_type_coercer.rb +29 -51
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
- data/lib/grape/validations/types/dry_type_coercer.rb +76 -0
- data/lib/grape/validations/types/file.rb +22 -18
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +46 -39
- data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
- data/lib/grape/validations/types/primitive_coercer.rb +67 -0
- data/lib/grape/validations/types/set_coercer.rb +40 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
- data/lib/grape/validations/validator_factory.rb +8 -11
- data/lib/grape/validations/validators/all_or_none.rb +8 -13
- data/lib/grape/validations/validators/allow_blank.rb +3 -1
- data/lib/grape/validations/validators/as.rb +5 -4
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -13
- data/lib/grape/validations/validators/base.rb +20 -16
- data/lib/grape/validations/validators/coerce.rb +46 -29
- data/lib/grape/validations/validators/default.rb +6 -6
- data/lib/grape/validations/validators/exactly_one_of.rb +10 -23
- data/lib/grape/validations/validators/except_values.rb +4 -2
- data/lib/grape/validations/validators/multiple_params_base.rb +17 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -18
- data/lib/grape/validations/validators/presence.rb +3 -1
- data/lib/grape/validations/validators/regexp.rb +4 -2
- data/lib/grape/validations/validators/same_as.rb +26 -0
- data/lib/grape/validations/validators/values.rb +18 -6
- data/lib/grape/version.rb +3 -1
- data/spec/grape/api/custom_validations_spec.rb +5 -3
- data/spec/grape/api/deeply_included_options_spec.rb +2 -0
- data/spec/grape/api/defines_boolean_in_params_spec.rb +39 -0
- data/spec/grape/api/inherited_helpers_spec.rb +2 -0
- data/spec/grape/api/instance_spec.rb +104 -0
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/nested_helpers_spec.rb +2 -0
- data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/parameters_modification_spec.rb +3 -1
- data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +2 -0
- data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +61 -0
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
- data/spec/grape/api/shared_helpers_spec.rb +2 -0
- data/spec/grape/api_remount_spec.rb +473 -0
- data/spec/grape/api_spec.rb +565 -12
- data/spec/grape/config_spec.rb +19 -0
- data/spec/grape/dsl/callbacks_spec.rb +2 -0
- data/spec/grape/dsl/configuration_spec.rb +2 -0
- data/spec/grape/dsl/desc_spec.rb +42 -16
- data/spec/grape/dsl/headers_spec.rb +2 -0
- data/spec/grape/dsl/helpers_spec.rb +4 -2
- data/spec/grape/dsl/inside_route_spec.rb +184 -33
- data/spec/grape/dsl/logger_spec.rb +2 -0
- data/spec/grape/dsl/middleware_spec.rb +10 -0
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +2 -0
- data/spec/grape/dsl/routing_spec.rb +12 -0
- data/spec/grape/dsl/settings_spec.rb +2 -0
- data/spec/grape/dsl/validations_spec.rb +2 -0
- data/spec/grape/endpoint/declared_spec.rb +601 -0
- data/spec/grape/endpoint_spec.rb +53 -523
- data/spec/grape/entity_spec.rb +9 -1
- data/spec/grape/exceptions/base_spec.rb +67 -0
- data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_response_spec.rb +13 -0
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
- data/spec/grape/exceptions/missing_option_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +8 -4
- data/spec/grape/exceptions/validation_spec.rb +3 -1
- data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
- data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
- data/spec/grape/integration/rack_sendfile_spec.rb +14 -8
- data/spec/grape/integration/rack_spec.rb +25 -7
- data/spec/grape/loading_spec.rb +2 -0
- data/spec/grape/middleware/auth/base_spec.rb +2 -0
- data/spec/grape/middleware/auth/dsl_spec.rb +5 -3
- data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
- data/spec/grape/middleware/base_spec.rb +10 -0
- data/spec/grape/middleware/error_spec.rb +3 -1
- data/spec/grape/middleware/exception_spec.rb +4 -2
- data/spec/grape/middleware/formatter_spec.rb +33 -16
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +12 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/header_spec.rb +9 -1
- data/spec/grape/middleware/versioner/param_spec.rb +3 -1
- data/spec/grape/middleware/versioner/path_spec.rb +3 -1
- data/spec/grape/middleware/versioner_spec.rb +2 -0
- data/spec/grape/named_api_spec.rb +21 -0
- data/spec/grape/parser_spec.rb +7 -5
- data/spec/grape/path_spec.rb +6 -4
- data/spec/grape/presenters/presenter_spec.rb +2 -0
- data/spec/grape/request_spec.rb +26 -0
- data/spec/grape/util/inheritable_setting_spec.rb +2 -0
- data/spec/grape/util/inheritable_values_spec.rb +2 -0
- data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
- data/spec/grape/util/stackable_values_spec.rb +3 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
- data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +41 -0
- data/spec/grape/validations/params_scope_spec.rb +213 -9
- data/spec/grape/validations/single_attribute_iterator_spec.rb +58 -0
- data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
- data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
- data/spec/grape/validations/types_spec.rb +9 -36
- data/spec/grape/validations/validators/all_or_none_spec.rb +140 -30
- data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +175 -29
- data/spec/grape/validations/validators/coerce_spec.rb +476 -135
- data/spec/grape/validations/validators/default_spec.rb +172 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +204 -38
- data/spec/grape/validations/validators/except_values_spec.rb +4 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +186 -27
- data/spec/grape/validations/validators/presence_spec.rb +30 -0
- data/spec/grape/validations/validators/regexp_spec.rb +2 -0
- data/spec/grape/validations/validators/same_as_spec.rb +65 -0
- data/spec/grape/validations/validators/values_spec.rb +30 -5
- data/spec/grape/validations_spec.rb +388 -50
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- data/spec/integration/multi_json/json_spec.rb +2 -0
- data/spec/integration/multi_xml/xml_spec.rb +2 -0
- data/spec/shared/versioning_examples.rb +22 -20
- data/spec/spec_helper.rb +12 -1
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/chunks.rb +14 -0
- data/spec/support/content_type_helpers.rb +2 -0
- data/spec/support/eager_load.rb +19 -0
- data/spec/support/endpoint_faker.rb +2 -0
- data/spec/support/file_streamer.rb +2 -0
- data/spec/support/integer_helpers.rb +2 -0
- data/spec/support/versioned_helpers.rb +8 -8
- metadata +86 -48
- data/Appraisals +0 -32
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile +0 -35
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_edge.gemfile +0 -35
- data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
- data/lib/grape/util/content_types.rb +0 -26
- data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
- data/pkg/grape-0.17.0.gem +0 -0
- data/pkg/grape-0.19.0.gem +0 -0
@@ -1,37 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_inheritable'
|
4
|
+
|
1
5
|
module Grape
|
2
6
|
module Util
|
3
|
-
class StackableValues
|
4
|
-
|
5
|
-
attr_accessor :new_values
|
6
|
-
attr_reader :frozen_values
|
7
|
-
|
8
|
-
def initialize(inherited_values = {})
|
9
|
-
@inherited_values = inherited_values
|
10
|
-
@new_values = {}
|
11
|
-
@frozen_values = {}
|
12
|
-
end
|
13
|
-
|
7
|
+
class StackableValues < BaseInheritable
|
8
|
+
# Even if there is no value, an empty array will be returned.
|
14
9
|
def [](name)
|
15
|
-
|
16
|
-
|
17
|
-
value = []
|
18
|
-
value.concat(@inherited_values[name] || [])
|
19
|
-
value.concat(@new_values[name] || [])
|
20
|
-
value
|
21
|
-
end
|
10
|
+
inherited_value = inherited_values[name]
|
11
|
+
new_value = new_values[name]
|
22
12
|
|
23
|
-
|
24
|
-
raise if @frozen_values.key? name
|
25
|
-
@new_values[name] ||= []
|
26
|
-
@new_values[name].push value
|
27
|
-
end
|
13
|
+
return new_value || [] unless inherited_value
|
28
14
|
|
29
|
-
|
30
|
-
new_values.delete key
|
15
|
+
concat_values(inherited_value, new_value)
|
31
16
|
end
|
32
17
|
|
33
|
-
def
|
34
|
-
|
18
|
+
def []=(name, value)
|
19
|
+
new_values[name] ||= []
|
20
|
+
new_values[name].push value
|
35
21
|
end
|
36
22
|
|
37
23
|
def to_hash
|
@@ -40,14 +26,15 @@ module Grape
|
|
40
26
|
end
|
41
27
|
end
|
42
28
|
|
43
|
-
|
44
|
-
|
45
|
-
|
29
|
+
protected
|
30
|
+
|
31
|
+
def concat_values(inherited_value, new_value)
|
32
|
+
return inherited_value unless new_value
|
46
33
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
34
|
+
[].tap do |value|
|
35
|
+
value.concat(inherited_value)
|
36
|
+
value.concat(new_value)
|
37
|
+
end
|
51
38
|
end
|
52
39
|
end
|
53
40
|
end
|
data/lib/grape/util/xml.rb
CHANGED
data/lib/grape/validations.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class AttributesIterator
|
@@ -29,9 +31,7 @@ module Grape
|
|
29
31
|
|
30
32
|
if @scope.type == Array
|
31
33
|
next unless @original_params.is_a?(Array) # do not validate content of array if it isn't array
|
32
|
-
|
33
|
-
end
|
34
|
-
if inside_array
|
34
|
+
|
35
35
|
# fill current and parent scopes with correct array indicies
|
36
36
|
parent_scope = @scope.parent
|
37
37
|
parent_indicies.each do |parent_index|
|
@@ -41,11 +41,21 @@ module Grape
|
|
41
41
|
@scope.index = index
|
42
42
|
end
|
43
43
|
|
44
|
-
@attrs
|
45
|
-
yield resource_params, attr_name, inside_array
|
46
|
-
end
|
44
|
+
yield_attributes(resource_params, @attrs, &block)
|
47
45
|
end
|
48
46
|
end
|
47
|
+
|
48
|
+
def yield_attributes(_resource_params, _attrs)
|
49
|
+
raise NotImplementedError
|
50
|
+
end
|
51
|
+
|
52
|
+
# This is a special case so that we can ignore tree's where option
|
53
|
+
# values are missing lower down. Unfortunately we can remove this
|
54
|
+
# are the parameter parsing stage as they are required to ensure
|
55
|
+
# the correct indexing is maintained
|
56
|
+
def skip?(val)
|
57
|
+
val == Grape::DSL::Parameters::EmptyOptionalValue
|
58
|
+
end
|
49
59
|
end
|
50
60
|
end
|
51
61
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
module Validations
|
5
|
+
class MultipleAttributesIterator < AttributesIterator
|
6
|
+
private
|
7
|
+
|
8
|
+
def yield_attributes(resource_params, _attrs)
|
9
|
+
yield resource_params, skip?(resource_params)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class ParamsScope
|
@@ -36,23 +38,32 @@ module Grape
|
|
36
38
|
configure_declared_params
|
37
39
|
end
|
38
40
|
|
41
|
+
def configuration
|
42
|
+
@api.configuration.respond_to?(:evaluate) ? @api.configuration.evaluate : @api.configuration
|
43
|
+
end
|
44
|
+
|
39
45
|
# @return [Boolean] whether or not this entire scope needs to be
|
40
46
|
# validated
|
41
47
|
def should_validate?(parameters)
|
42
|
-
|
43
|
-
|
48
|
+
scoped_params = params(parameters)
|
49
|
+
|
50
|
+
return false if @optional && (scoped_params.blank? || all_element_blank?(scoped_params))
|
51
|
+
return false unless meets_dependency?(scoped_params, parameters)
|
44
52
|
return true if parent.nil?
|
45
53
|
parent.should_validate?(parameters)
|
46
54
|
end
|
47
55
|
|
48
56
|
def meets_dependency?(params, request_params)
|
57
|
+
return true unless @dependent_on
|
58
|
+
|
49
59
|
if @parent.present? && !@parent.meets_dependency?(@parent.params(request_params), request_params)
|
50
60
|
return false
|
51
61
|
end
|
52
62
|
|
53
|
-
return true unless @dependent_on
|
54
63
|
return params.any? { |param| meets_dependency?(param, request_params) } if params.is_a?(Array)
|
55
|
-
|
64
|
+
|
65
|
+
# params might be anything what looks like a hash, so it must implement a `key?` method
|
66
|
+
return false unless params.respond_to?(:key?)
|
56
67
|
|
57
68
|
@dependent_on.each do |dependency|
|
58
69
|
if dependency.is_a?(Hash)
|
@@ -71,7 +82,7 @@ module Grape
|
|
71
82
|
def full_name(name, index: nil)
|
72
83
|
if nested?
|
73
84
|
# Find our containing element's name, and append ours.
|
74
|
-
|
85
|
+
"#{@parent.full_name(@element)}#{brackets(@index || index)}#{brackets(name)}"
|
75
86
|
elsif lateral?
|
76
87
|
# Find the name of the element as if it was at the same nesting level
|
77
88
|
# as our parent. We need to forward our index upward to achieve this.
|
@@ -116,11 +127,12 @@ module Grape
|
|
116
127
|
# @param attrs [Array] (see Grape::DSL::Parameters#requires)
|
117
128
|
def push_declared_params(attrs, **opts)
|
118
129
|
if lateral?
|
119
|
-
@parent.push_declared_params(attrs, opts)
|
130
|
+
@parent.push_declared_params(attrs, **opts)
|
120
131
|
else
|
121
132
|
if opts && opts[:as]
|
122
|
-
@api.route_setting(:
|
123
|
-
@api.route_setting(:
|
133
|
+
@api.route_setting(:renamed_params, @api.route_setting(:renamed_params) || [])
|
134
|
+
@api.route_setting(:renamed_params) << { attrs.first => opts[:as] }
|
135
|
+
attrs = [opts[:as]]
|
124
136
|
end
|
125
137
|
|
126
138
|
@declared_params.concat attrs
|
@@ -178,14 +190,12 @@ module Grape
|
|
178
190
|
raise Grape::Exceptions::UnsupportedGroupTypeError.new unless Grape::Validations::Types.group?(type)
|
179
191
|
end
|
180
192
|
|
181
|
-
opts = attrs[1] || { type: Array }
|
182
|
-
|
183
193
|
self.class.new(
|
184
194
|
api: @api,
|
185
|
-
element: attrs.first,
|
195
|
+
element: attrs[1][:as] || attrs.first,
|
186
196
|
parent: self,
|
187
197
|
optional: optional,
|
188
|
-
type:
|
198
|
+
type: type || Array,
|
189
199
|
&block
|
190
200
|
)
|
191
201
|
end
|
@@ -229,14 +239,14 @@ module Grape
|
|
229
239
|
@parent.push_declared_params [element => @declared_params]
|
230
240
|
else
|
231
241
|
@api.namespace_stackable(:declared_params, @declared_params)
|
232
|
-
|
233
|
-
@api.route_setting(:declared_params, []) unless @api.route_setting(:declared_params)
|
234
|
-
@api.route_setting(:declared_params, @api.namespace_stackable(:declared_params).flatten)
|
235
242
|
end
|
243
|
+
|
244
|
+
# params were stored in settings, it can be cleaned from the params scope
|
245
|
+
@declared_params = nil
|
236
246
|
end
|
237
247
|
|
238
248
|
def validates(attrs, validations)
|
239
|
-
doc_attrs = { required: validations.
|
249
|
+
doc_attrs = { required: validations.key?(:presence) }
|
240
250
|
|
241
251
|
coerce_type = infer_coercion(validations)
|
242
252
|
|
@@ -276,9 +286,7 @@ module Grape
|
|
276
286
|
full_attrs = attrs.collect { |name| { name: name, full_name: full_name(name) } }
|
277
287
|
@api.document_attribute(full_attrs, doc_attrs)
|
278
288
|
|
279
|
-
|
280
|
-
opts = {}
|
281
|
-
opts[:fail_fast] = validations.delete(:fail_fast) || false
|
289
|
+
opts = derive_validator_options(validations)
|
282
290
|
|
283
291
|
# Validate for presence before any other validators
|
284
292
|
if validations.key?(:presence) && validations[:presence]
|
@@ -406,13 +414,15 @@ module Grape
|
|
406
414
|
|
407
415
|
raise Grape::Exceptions::UnknownValidator.new(type) unless validator_class
|
408
416
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
417
|
+
validator_options = {
|
418
|
+
attributes: attrs,
|
419
|
+
options: options,
|
420
|
+
required: doc_attrs[:required],
|
421
|
+
params_scope: self,
|
422
|
+
opts: opts,
|
423
|
+
validator_class: validator_class
|
424
|
+
}
|
425
|
+
@api.namespace_stackable(:validations, validator_options)
|
416
426
|
end
|
417
427
|
|
418
428
|
def validate_value_coercion(coerce_type, *values_list)
|
@@ -421,8 +431,8 @@ module Grape
|
|
421
431
|
values_list.each do |values|
|
422
432
|
next if !values || values.is_a?(Proc)
|
423
433
|
value_types = values.is_a?(Range) ? [values.begin, values.end] : values
|
424
|
-
if coerce_type ==
|
425
|
-
value_types = value_types.map { |type|
|
434
|
+
if coerce_type == Grape::API::Boolean
|
435
|
+
value_types = value_types.map { |type| Grape::API::Boolean.build(type) }
|
426
436
|
end
|
427
437
|
unless value_types.all? { |v| v.is_a? coerce_type }
|
428
438
|
raise Grape::Exceptions::IncompatibleOptionValues.new(:type, coerce_type, :values, values)
|
@@ -440,8 +450,19 @@ module Grape
|
|
440
450
|
validations[type].respond_to?(:key?) && validations[type].key?(key) && !validations[type][key].nil?
|
441
451
|
end
|
442
452
|
|
443
|
-
def all_element_blank?(
|
444
|
-
|
453
|
+
def all_element_blank?(scoped_params)
|
454
|
+
scoped_params.respond_to?(:all?) && scoped_params.all?(&:blank?)
|
455
|
+
end
|
456
|
+
|
457
|
+
# Validators don't have access to each other and they don't need, however,
|
458
|
+
# some validators might influence others, so their options should be shared
|
459
|
+
def derive_validator_options(validations)
|
460
|
+
allow_blank = validations[:allow_blank]
|
461
|
+
|
462
|
+
{
|
463
|
+
allow_blank: allow_blank.is_a?(Hash) ? allow_blank[:value] : allow_blank,
|
464
|
+
fail_fast: validations.delete(:fail_fast) || false
|
465
|
+
}
|
445
466
|
end
|
446
467
|
end
|
447
468
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
module Validations
|
5
|
+
class SingleAttributeIterator < AttributesIterator
|
6
|
+
private
|
7
|
+
|
8
|
+
def yield_attributes(val, attrs)
|
9
|
+
attrs.each do |attr_name|
|
10
|
+
yield val, attr_name, empty?(val), skip?(val)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Primitives like Integers and Booleans don't respond to +empty?+.
|
15
|
+
# It could be possible to use +blank?+ instead, but
|
16
|
+
#
|
17
|
+
# false.blank?
|
18
|
+
# => true
|
19
|
+
def empty?(val)
|
20
|
+
val.respond_to?(:empty?) ? val.empty? : val.nil?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'types/build_coercer'
|
2
4
|
require_relative 'types/custom_type_coercer'
|
3
5
|
require_relative 'types/custom_type_collection_coercer'
|
@@ -5,10 +7,7 @@ require_relative 'types/multiple_type_coercer'
|
|
5
7
|
require_relative 'types/variant_collection_coercer'
|
6
8
|
require_relative 'types/json'
|
7
9
|
require_relative 'types/file'
|
8
|
-
|
9
|
-
# Patch for Virtus::Attribute::Collection
|
10
|
-
# See the file for more details
|
11
|
-
require_relative 'types/virtus_collection_patch'
|
10
|
+
require_relative 'types/invalid_value'
|
12
11
|
|
13
12
|
module Grape
|
14
13
|
module Validations
|
@@ -23,12 +22,7 @@ module Grape
|
|
23
22
|
# and {Grape::Dsl::Parameters#optional}. The main
|
24
23
|
# entry point for this process is {Types.build_coercer}.
|
25
24
|
module Types
|
26
|
-
#
|
27
|
-
# a parameter value could not be coerced.
|
28
|
-
class InvalidValue; end
|
29
|
-
|
30
|
-
# Types representing a single value, which are coerced through Virtus
|
31
|
-
# or special logic in Grape.
|
25
|
+
# Types representing a single value, which are coerced.
|
32
26
|
PRIMITIVES = [
|
33
27
|
# Numerical
|
34
28
|
Integer,
|
@@ -42,10 +36,11 @@ module Grape
|
|
42
36
|
Time,
|
43
37
|
|
44
38
|
# Misc
|
45
|
-
|
39
|
+
Grape::API::Boolean,
|
46
40
|
String,
|
47
41
|
Symbol,
|
48
|
-
|
42
|
+
TrueClass,
|
43
|
+
FalseClass
|
49
44
|
].freeze
|
50
45
|
|
51
46
|
# Types representing data structures.
|
@@ -55,8 +50,7 @@ module Grape
|
|
55
50
|
Set
|
56
51
|
].freeze
|
57
52
|
|
58
|
-
#
|
59
|
-
# and type-checking logic.
|
53
|
+
# Special custom types provided by Grape.
|
60
54
|
SPECIAL = {
|
61
55
|
JSON => Json,
|
62
56
|
Array[JSON] => JsonArray,
|
@@ -86,8 +80,6 @@ module Grape
|
|
86
80
|
# @param type [Class] type to check
|
87
81
|
# @return [Boolean] whether or not the type is known by Grape as a valid
|
88
82
|
# data structure type
|
89
|
-
# @note This method does not yet consider 'complex types', which inherit
|
90
|
-
# Virtus.model.
|
91
83
|
def self.structure?(type)
|
92
84
|
STRUCTURES.include?(type)
|
93
85
|
end
|
@@ -104,25 +96,6 @@ module Grape
|
|
104
96
|
(type.is_a?(Array) || type.is_a?(Set)) && type.size > 1
|
105
97
|
end
|
106
98
|
|
107
|
-
# Does the given class implement a type system that Grape
|
108
|
-
# (i.e. the underlying virtus attribute system) supports
|
109
|
-
# out-of-the-box? Currently supported are +axiom-types+
|
110
|
-
# and +virtus+.
|
111
|
-
#
|
112
|
-
# The type will be passed to +Virtus::Attribute.build+,
|
113
|
-
# and the resulting attribute object will be expected to
|
114
|
-
# respond correctly to +coerce+ and +value_coerced?+.
|
115
|
-
#
|
116
|
-
# @param type [Class] type to check
|
117
|
-
# @return [Boolean] +true+ where the type is recognized
|
118
|
-
def self.recognized?(type)
|
119
|
-
return false if type.is_a?(Array) || type.is_a?(Set)
|
120
|
-
|
121
|
-
type.is_a?(Virtus::Attribute) ||
|
122
|
-
type.ancestors.include?(Axiom::Types::Type) ||
|
123
|
-
type.include?(Virtus::Model::Core)
|
124
|
-
end
|
125
|
-
|
126
99
|
# Does Grape provide special coercion and validation
|
127
100
|
# routines for the given class? This does not include
|
128
101
|
# automatic handling for primitives, structures and
|
@@ -152,8 +125,6 @@ module Grape
|
|
152
125
|
!primitive?(type) &&
|
153
126
|
!structure?(type) &&
|
154
127
|
!multiple?(type) &&
|
155
|
-
!recognized?(type) &&
|
156
|
-
!special?(type) &&
|
157
128
|
type.respond_to?(:parse) &&
|
158
129
|
type.method(:parse).arity == 1
|
159
130
|
end
|
@@ -166,7 +137,11 @@ module Grape
|
|
166
137
|
def self.collection_of_custom?(type)
|
167
138
|
(type.is_a?(Array) || type.is_a?(Set)) &&
|
168
139
|
type.length == 1 &&
|
169
|
-
custom?(type.first)
|
140
|
+
(custom?(type.first) || special?(type.first))
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.map_special(type)
|
144
|
+
SPECIAL.fetch(type, type)
|
170
145
|
end
|
171
146
|
end
|
172
147
|
end
|