grape 1.5.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +75 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +152 -21
- data/UPGRADING.md +86 -2
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +14 -18
- data/lib/grape/api.rb +18 -13
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/api.rb +0 -2
- data/lib/grape/dsl/callbacks.rb +0 -2
- data/lib/grape/dsl/configuration.rb +0 -2
- data/lib/grape/dsl/desc.rb +2 -19
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -7
- data/lib/grape/dsl/inside_route.rb +43 -30
- data/lib/grape/dsl/middleware.rb +4 -6
- data/lib/grape/dsl/parameters.rb +8 -10
- data/lib/grape/dsl/request_response.rb +9 -8
- data/lib/grape/dsl/routing.rb +6 -4
- data/lib/grape/dsl/settings.rb +5 -7
- data/lib/grape/dsl/validations.rb +0 -15
- data/lib/grape/endpoint.rb +21 -36
- data/lib/grape/error_formatter/json.rb +9 -7
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/missing_group_type.rb +8 -1
- data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
- data/lib/grape/exceptions/validation.rb +1 -6
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/locale/en.yml +9 -8
- data/lib/grape/middleware/auth/dsl.rb +7 -2
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +2 -2
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +5 -0
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_doc.rb +58 -0
- data/lib/grape/validations/params_scope.rb +137 -78
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +16 -8
- data/lib/grape/validations/types/set_coercer.rb +0 -2
- data/lib/grape/validations/types.rb +98 -30
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +82 -70
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/validations.rb +16 -6
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +70 -29
- data/spec/grape/api/custom_validations_spec.rb +116 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -5
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
- data/spec/grape/api/documentation_spec.rb +59 -0
- data/spec/grape/api/inherited_helpers_spec.rb +0 -2
- data/spec/grape/api/instance_spec.rb +0 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -2
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/nested_helpers_spec.rb +0 -2
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/parameters_modification_spec.rb +0 -2
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
- data/spec/grape/api/recognize_path_spec.rb +1 -3
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
- data/spec/grape/api/shared_helpers_spec.rb +0 -2
- data/spec/grape/api_remount_spec.rb +16 -16
- data/spec/grape/api_spec.rb +527 -224
- data/spec/grape/config_spec.rb +0 -2
- data/spec/grape/dsl/callbacks_spec.rb +2 -3
- data/spec/grape/dsl/configuration_spec.rb +0 -2
- data/spec/grape/dsl/desc_spec.rb +0 -2
- data/spec/grape/dsl/headers_spec.rb +39 -11
- data/spec/grape/dsl/helpers_spec.rb +3 -4
- data/spec/grape/dsl/inside_route_spec.rb +16 -16
- data/spec/grape/dsl/logger_spec.rb +15 -19
- data/spec/grape/dsl/middleware_spec.rb +2 -3
- data/spec/grape/dsl/parameters_spec.rb +2 -2
- data/spec/grape/dsl/request_response_spec.rb +7 -8
- data/spec/grape/dsl/routing_spec.rb +11 -10
- data/spec/grape/dsl/settings_spec.rb +0 -2
- data/spec/grape/dsl/validations_spec.rb +0 -17
- data/spec/grape/endpoint/declared_spec.rb +261 -16
- data/spec/grape/endpoint_spec.rb +98 -57
- data/spec/grape/entity_spec.rb +22 -23
- data/spec/grape/exceptions/base_spec.rb +16 -2
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
- data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
- data/spec/grape/exceptions/missing_option_spec.rb +1 -3
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
- data/spec/grape/exceptions/validation_spec.rb +5 -5
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
- data/spec/grape/integration/rack_spec.rb +0 -2
- data/spec/grape/loading_spec.rb +8 -10
- data/spec/grape/middleware/auth/base_spec.rb +0 -1
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
- data/spec/grape/middleware/base_spec.rb +24 -17
- data/spec/grape/middleware/error_spec.rb +8 -3
- data/spec/grape/middleware/exception_spec.rb +111 -163
- data/spec/grape/middleware/formatter_spec.rb +27 -8
- data/spec/grape/middleware/globals_spec.rb +7 -6
- data/spec/grape/middleware/stack_spec.rb +14 -14
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
- data/spec/grape/middleware/versioner/header_spec.rb +30 -15
- data/spec/grape/middleware/versioner/param_spec.rb +7 -3
- data/spec/grape/middleware/versioner/path_spec.rb +5 -3
- data/spec/grape/middleware/versioner_spec.rb +1 -3
- data/spec/grape/named_api_spec.rb +0 -2
- data/spec/grape/parser_spec.rb +4 -2
- data/spec/grape/path_spec.rb +52 -54
- data/spec/grape/presenters/presenter_spec.rb +7 -8
- data/spec/grape/request_spec.rb +6 -6
- data/spec/grape/util/inheritable_setting_spec.rb +7 -8
- data/spec/grape/util/inheritable_values_spec.rb +3 -3
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
- data/spec/grape/util/stackable_values_spec.rb +7 -6
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
- data/spec/grape/validations/attributes_doc_spec.rb +153 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
- data/spec/grape/validations/params_scope_spec.rb +361 -96
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
- data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
- data/spec/grape/validations/types_spec.rb +36 -10
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
- data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
- data/spec/grape/validations/validators/coerce_spec.rb +99 -24
- data/spec/grape/validations/validators/default_spec.rb +72 -80
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
- data/spec/grape/validations/validators/except_values_spec.rb +3 -5
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
- data/spec/grape/validations/validators/presence_spec.rb +16 -3
- data/spec/grape/validations/validators/regexp_spec.rb +25 -33
- data/spec/grape/validations/validators/same_as_spec.rb +14 -22
- data/spec/grape/validations/validators/values_spec.rb +182 -179
- data/spec/grape/validations_spec.rb +149 -80
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -3
- data/spec/integration/multi_xml/xml_spec.rb +1 -3
- data/spec/shared/versioning_examples.rb +12 -9
- data/spec/spec_helper.rb +21 -6
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +125 -115
- data/lib/grape/validations/validators/all_or_none.rb +0 -15
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -16
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
- data/lib/grape/validations/validators/coerce.rb +0 -91
- data/lib/grape/validations/validators/default.rb +0 -48
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
- data/lib/grape/validations/validators/presence.rb +0 -12
- data/lib/grape/validations/validators/regexp.rb +0 -13
- data/lib/grape/validations/validators/same_as.rb +0 -26
- data/lib/grape/validations/validators/values.rb +0 -83
- data/spec/support/eager_load.rb +0 -19
data/lib/grape/api.rb
CHANGED
@@ -10,6 +10,18 @@ module Grape
|
|
10
10
|
# Class methods that we want to call on the API rather than on the API object
|
11
11
|
NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile! inherited]).freeze
|
12
12
|
|
13
|
+
class Boolean
|
14
|
+
def self.build(val)
|
15
|
+
return nil if val != true && val != false
|
16
|
+
|
17
|
+
new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Instance
|
22
|
+
Boolean = Grape::API::Boolean
|
23
|
+
end
|
24
|
+
|
13
25
|
class << self
|
14
26
|
attr_accessor :base_instance, :instances
|
15
27
|
|
@@ -20,10 +32,11 @@ module Grape
|
|
20
32
|
|
21
33
|
# When inherited, will create a list of all instances (times the API was mounted)
|
22
34
|
# It will listen to the setup required to mount that endpoint, and replicate it on any new instance
|
23
|
-
def inherited(api
|
24
|
-
|
35
|
+
def inherited(api)
|
36
|
+
super
|
37
|
+
|
38
|
+
api.initial_setup(Grape::API == self ? Grape::API::Instance : @base_instance)
|
25
39
|
api.override_all_methods!
|
26
|
-
make_inheritable(api)
|
27
40
|
end
|
28
41
|
|
29
42
|
# Initialize the instance variables on the remountable class, and the base_instance
|
@@ -68,15 +81,6 @@ module Grape
|
|
68
81
|
instance_for_rack.call(*args, &block)
|
69
82
|
end
|
70
83
|
|
71
|
-
# Allows an API to itself be inheritable:
|
72
|
-
def make_inheritable(api)
|
73
|
-
# When a child API inherits from a parent API.
|
74
|
-
def api.inherited(child_api)
|
75
|
-
# The instances of the child API inherit from the instances of the parent API
|
76
|
-
Grape::API.inherited(child_api, base_instance)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
84
|
# Alleviates problems with autoloading by tring to search for the constant
|
81
85
|
def const_missing(*args)
|
82
86
|
if base_instance.const_defined?(*args)
|
@@ -141,7 +145,7 @@ module Grape
|
|
141
145
|
# Adds a new stage to the set up require to get a Grape::API up and running
|
142
146
|
def add_setup(method, *args, &block)
|
143
147
|
setup_step = { method: method, args: args, block: block }
|
144
|
-
@setup
|
148
|
+
@setup += [setup_step]
|
145
149
|
last_response = nil
|
146
150
|
@instances.each do |instance|
|
147
151
|
last_response = replay_step_on(instance, setup_step)
|
@@ -151,6 +155,7 @@ module Grape
|
|
151
155
|
|
152
156
|
def replay_step_on(instance, setup_step)
|
153
157
|
return if skip_immediate_run?(instance, setup_step[:args])
|
158
|
+
|
154
159
|
args = evaluate_arguments(instance.configuration, *setup_step[:args])
|
155
160
|
response = instance.send(setup_step[:method], *args, &setup_step[:block])
|
156
161
|
if skip_immediate_run?(instance, [response])
|
data/lib/grape/cookies.rb
CHANGED
@@ -33,9 +33,11 @@ module Grape
|
|
33
33
|
@cookies.each(&block)
|
34
34
|
end
|
35
35
|
|
36
|
+
# rubocop:disable Layout/SpaceBeforeBrackets
|
36
37
|
def delete(name, **opts)
|
37
38
|
options = opts.merge(value: 'deleted', expires: Time.at(0))
|
38
39
|
self.[]=(name, options)
|
39
40
|
end
|
41
|
+
# rubocop:enable Layout/SpaceBeforeBrackets
|
40
42
|
end
|
41
43
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry-types'
|
4
|
+
|
5
|
+
module Grape
|
6
|
+
module DryTypes
|
7
|
+
# Call +Dry.Types()+ to add all registered types to +DryTypes+ which is
|
8
|
+
# a container in this case. Check documentation for more information
|
9
|
+
# https://dry-rb.org/gems/dry-types/1.2/getting-started/
|
10
|
+
include Dry.Types()
|
11
|
+
end
|
12
|
+
end
|
data/lib/grape/dsl/api.rb
CHANGED
data/lib/grape/dsl/callbacks.rb
CHANGED
data/lib/grape/dsl/desc.rb
CHANGED
@@ -50,7 +50,7 @@ module Grape
|
|
50
50
|
# end
|
51
51
|
#
|
52
52
|
def desc(description, options = {}, &config_block)
|
53
|
-
if
|
53
|
+
if config_block
|
54
54
|
endpoint_configuration = if defined?(configuration)
|
55
55
|
# When the instance is mounted - the configuration is executed on mount time
|
56
56
|
if configuration.respond_to?(:evaluate)
|
@@ -68,9 +68,7 @@ module Grape
|
|
68
68
|
end
|
69
69
|
|
70
70
|
config_class.configure(&config_block)
|
71
|
-
unless options.empty?
|
72
|
-
warn '[DEPRECATION] Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.'
|
73
|
-
end
|
71
|
+
warn '[DEPRECATION] Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.' unless options.empty?
|
74
72
|
options = config_class.settings
|
75
73
|
else
|
76
74
|
options = options.merge(description: description)
|
@@ -80,21 +78,6 @@ module Grape
|
|
80
78
|
route_setting :description, options
|
81
79
|
end
|
82
80
|
|
83
|
-
def description_field(field, value = nil)
|
84
|
-
description = route_setting(:description)
|
85
|
-
if value
|
86
|
-
description ||= route_setting(:description, {})
|
87
|
-
description[field] = value
|
88
|
-
elsif description
|
89
|
-
description[field]
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def unset_description_field(field)
|
94
|
-
description = route_setting(:description)
|
95
|
-
description.delete(field) if description
|
96
|
-
end
|
97
|
-
|
98
81
|
# Returns an object which configures itself via an instance-context DSL.
|
99
82
|
def desc_container(endpoint_configuration)
|
100
83
|
Module.new do
|
data/lib/grape/dsl/headers.rb
CHANGED
@@ -3,8 +3,11 @@
|
|
3
3
|
module Grape
|
4
4
|
module DSL
|
5
5
|
module Headers
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# This method has four responsibilities:
|
7
|
+
# 1. Set a specifc header value by key
|
8
|
+
# 2. Retrieve a specifc header value by key
|
9
|
+
# 3. Retrieve all headers that have been set
|
10
|
+
# 4. Delete a specifc header key-value pair
|
8
11
|
def header(key = nil, val = nil)
|
9
12
|
if key
|
10
13
|
val ? header[key.to_s] = val : header.delete(key.to_s)
|
data/lib/grape/dsl/helpers.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Helpers
|
@@ -36,8 +34,8 @@ module Grape
|
|
36
34
|
#
|
37
35
|
def helpers(*new_modules, &block)
|
38
36
|
include_new_modules(new_modules) if new_modules.any?
|
39
|
-
include_block(block) if
|
40
|
-
include_all_in_scope if !
|
37
|
+
include_block(block) if block
|
38
|
+
include_all_in_scope if !block && new_modules.empty?
|
41
39
|
end
|
42
40
|
|
43
41
|
protected
|
@@ -67,12 +65,13 @@ module Grape
|
|
67
65
|
|
68
66
|
def define_boolean_in_mod(mod)
|
69
67
|
return if defined? mod::Boolean
|
70
|
-
|
68
|
+
|
69
|
+
mod.const_set(:Boolean, Grape::API::Boolean)
|
71
70
|
end
|
72
71
|
|
73
|
-
def inject_api_helpers_to_mod(mod, &
|
72
|
+
def inject_api_helpers_to_mod(mod, &block)
|
74
73
|
mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
|
75
|
-
yield if
|
74
|
+
yield if block
|
76
75
|
mod.api_changed(self)
|
77
76
|
end
|
78
77
|
end
|
@@ -96,6 +95,7 @@ module Grape
|
|
96
95
|
|
97
96
|
def process_named_params
|
98
97
|
return unless instance_variable_defined?(:@named_params) && @named_params && @named_params.any?
|
98
|
+
|
99
99
|
api.namespace_stackable(:named_params, @named_params)
|
100
100
|
end
|
101
101
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
3
|
require 'grape/dsl/headers'
|
5
4
|
|
6
5
|
module Grape
|
@@ -29,7 +28,7 @@ module Grape
|
|
29
28
|
# has completed
|
30
29
|
module PostBeforeFilter
|
31
30
|
def declared(passed_params, options = {}, declared_params = nil, params_nested_path = [])
|
32
|
-
options = options.reverse_merge(include_missing: true, include_parent_namespaces: true)
|
31
|
+
options = options.reverse_merge(include_missing: true, include_parent_namespaces: true, evaluate_given: false)
|
33
32
|
declared_params ||= optioned_declared_params(**options)
|
34
33
|
|
35
34
|
if passed_params.is_a?(Array)
|
@@ -48,37 +47,47 @@ module Grape
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def declared_hash(passed_params, options, declared_params, params_nested_path)
|
51
|
-
declared_params.each_with_object(passed_params.class.new) do |
|
52
|
-
if
|
53
|
-
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
54
|
-
params_nested_path_dup = params_nested_path.dup
|
55
|
-
params_nested_path_dup << declared_parent_param.to_s
|
56
|
-
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
|
57
|
-
|
58
|
-
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
|
59
|
-
memo_key = optioned_param_key(declared_parent_param, options)
|
60
|
-
|
61
|
-
memo[memo_key] = handle_passed_param(params_nested_path_dup, passed_children_params.any?) do
|
62
|
-
declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
else
|
66
|
-
# If it is not a Hash then it does not have children.
|
67
|
-
# Find its value or set it to nil.
|
68
|
-
has_renaming = route_setting(:renamed_params) && route_setting(:renamed_params).find { |current| current[declared_param] }
|
69
|
-
param_renaming = has_renaming[declared_param] if has_renaming
|
70
|
-
|
71
|
-
next unless options[:include_missing] || passed_params.key?(declared_param) || (param_renaming && passed_params.key?(param_renaming))
|
50
|
+
declared_params.each_with_object(passed_params.class.new) do |declared_param_attr, memo|
|
51
|
+
next if options[:evaluate_given] && !declared_param_attr.scope.attr_meets_dependency?(passed_params)
|
72
52
|
|
73
|
-
|
74
|
-
|
53
|
+
declared_hash_attr(passed_params, options, declared_param_attr.key, params_nested_path, memo)
|
54
|
+
end
|
55
|
+
end
|
75
56
|
|
57
|
+
def declared_hash_attr(passed_params, options, declared_param, params_nested_path, memo)
|
58
|
+
renamed_params = route_setting(:renamed_params) || {}
|
59
|
+
if declared_param.is_a?(Hash)
|
60
|
+
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
76
61
|
params_nested_path_dup = params_nested_path.dup
|
77
|
-
params_nested_path_dup <<
|
78
|
-
|
79
|
-
|
62
|
+
params_nested_path_dup << declared_parent_param.to_s
|
63
|
+
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
|
64
|
+
|
65
|
+
rename_path = params_nested_path + [declared_parent_param.to_s]
|
66
|
+
renamed_param_name = renamed_params[rename_path]
|
67
|
+
|
68
|
+
memo_key = optioned_param_key(renamed_param_name || declared_parent_param, options)
|
69
|
+
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
|
70
|
+
|
71
|
+
memo[memo_key] = handle_passed_param(params_nested_path_dup, passed_children_params.any?) do
|
72
|
+
declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
|
80
73
|
end
|
81
74
|
end
|
75
|
+
else
|
76
|
+
# If it is not a Hash then it does not have children.
|
77
|
+
# Find its value or set it to nil.
|
78
|
+
return unless options[:include_missing] || passed_params.key?(declared_param)
|
79
|
+
|
80
|
+
rename_path = params_nested_path + [declared_param.to_s]
|
81
|
+
renamed_param_name = renamed_params[rename_path]
|
82
|
+
|
83
|
+
memo_key = optioned_param_key(renamed_param_name || declared_param, options)
|
84
|
+
passed_param = passed_params[declared_param]
|
85
|
+
|
86
|
+
params_nested_path_dup = params_nested_path.dup
|
87
|
+
params_nested_path_dup << declared_param.to_s
|
88
|
+
memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup) do
|
89
|
+
passed_param
|
90
|
+
end
|
82
91
|
end
|
83
92
|
end
|
84
93
|
|
@@ -86,7 +95,7 @@ module Grape
|
|
86
95
|
return yield if has_passed_children
|
87
96
|
|
88
97
|
key = params_nested_path[0]
|
89
|
-
key +=
|
98
|
+
key += "[#{params_nested_path[1..-1].join('][')}]" if params_nested_path.size > 1
|
90
99
|
|
91
100
|
route_options_params = options[:route_options][:params] || {}
|
92
101
|
type = route_options_params.dig(key, :type)
|
@@ -94,7 +103,7 @@ module Grape
|
|
94
103
|
|
95
104
|
if type == 'Hash' && !has_children
|
96
105
|
{}
|
97
|
-
elsif type == 'Array' || type&.start_with?('[') && !type&.include?(',')
|
106
|
+
elsif type == 'Array' || (type&.start_with?('[') && !type&.include?(','))
|
98
107
|
[]
|
99
108
|
elsif type == 'Set' || type&.start_with?('#<Set')
|
100
109
|
Set.new
|
@@ -117,6 +126,7 @@ module Grape
|
|
117
126
|
end
|
118
127
|
|
119
128
|
raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
|
129
|
+
|
120
130
|
declared_params
|
121
131
|
end
|
122
132
|
end
|
@@ -187,11 +197,13 @@ module Grape
|
|
187
197
|
case status
|
188
198
|
when Symbol
|
189
199
|
raise ArgumentError, "Status code :#{status} is invalid." unless Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(status)
|
200
|
+
|
190
201
|
@status = Rack::Utils.status_code(status)
|
191
202
|
when Integer
|
192
203
|
@status = status
|
193
204
|
when nil
|
194
205
|
return @status if instance_variable_defined?(:@status) && @status
|
206
|
+
|
195
207
|
case request.request_method.to_s.upcase
|
196
208
|
when Grape::Http::Headers::POST
|
197
209
|
201
|
@@ -369,6 +381,7 @@ module Grape
|
|
369
381
|
representation = (body || {}).merge(key => representation)
|
370
382
|
elsif entity_class.present? && body
|
371
383
|
raise ArgumentError, "Representation of type #{representation.class} cannot be merged." unless representation.respond_to?(:merge)
|
384
|
+
|
372
385
|
representation = body.merge(representation)
|
373
386
|
end
|
374
387
|
|
data/lib/grape/dsl/middleware.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Middleware
|
@@ -18,28 +16,28 @@ module Grape
|
|
18
16
|
# to inject.
|
19
17
|
def use(middleware_class, *args, &block)
|
20
18
|
arr = [:use, middleware_class, *args]
|
21
|
-
arr << block if
|
19
|
+
arr << block if block
|
22
20
|
|
23
21
|
namespace_stackable(:middleware, arr)
|
24
22
|
end
|
25
23
|
|
26
24
|
def insert(*args, &block)
|
27
25
|
arr = [:insert, *args]
|
28
|
-
arr << block if
|
26
|
+
arr << block if block
|
29
27
|
|
30
28
|
namespace_stackable(:middleware, arr)
|
31
29
|
end
|
32
30
|
|
33
31
|
def insert_before(*args, &block)
|
34
32
|
arr = [:insert_before, *args]
|
35
|
-
arr << block if
|
33
|
+
arr << block if block
|
36
34
|
|
37
35
|
namespace_stackable(:middleware, arr)
|
38
36
|
end
|
39
37
|
|
40
38
|
def insert_after(*args, &block)
|
41
39
|
arr = [:insert_after, *args]
|
42
|
-
arr << block if
|
40
|
+
arr << block if block
|
43
41
|
|
44
42
|
namespace_stackable(:middleware, arr)
|
45
43
|
end
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
# Defines DSL methods, meant to be applied to a ParamsScope, which define
|
@@ -64,7 +62,7 @@ module Grape
|
|
64
62
|
params_block = named_params.fetch(name) do
|
65
63
|
raise "Params :#{name} not found!"
|
66
64
|
end
|
67
|
-
instance_exec(options, ¶ms_block)
|
65
|
+
instance_exec(**options, ¶ms_block)
|
68
66
|
end
|
69
67
|
end
|
70
68
|
alias use_scope use
|
@@ -133,7 +131,7 @@ module Grape
|
|
133
131
|
require_required_and_optional_fields(attrs.first, opts)
|
134
132
|
else
|
135
133
|
validate_attributes(attrs, opts, &block)
|
136
|
-
|
134
|
+
block ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
|
137
135
|
end
|
138
136
|
end
|
139
137
|
|
@@ -149,9 +147,9 @@ module Grape
|
|
149
147
|
opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
|
150
148
|
|
151
149
|
# check type for optional parameter group
|
152
|
-
if attrs &&
|
153
|
-
raise Grape::Exceptions::
|
154
|
-
raise Grape::Exceptions::
|
150
|
+
if attrs && block
|
151
|
+
raise Grape::Exceptions::MissingGroupType if type.nil?
|
152
|
+
raise Grape::Exceptions::UnsupportedGroupType unless Grape::Validations::Types.group?(type)
|
155
153
|
end
|
156
154
|
|
157
155
|
if opts[:using]
|
@@ -159,7 +157,7 @@ module Grape
|
|
159
157
|
else
|
160
158
|
validate_attributes(attrs, opts, &block)
|
161
159
|
|
162
|
-
|
160
|
+
block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
|
163
161
|
end
|
164
162
|
end
|
165
163
|
|
@@ -219,8 +217,8 @@ module Grape
|
|
219
217
|
else
|
220
218
|
# @declared_params also includes hashes of options and such, but those
|
221
219
|
# won't be flattened out.
|
222
|
-
@declared_params.flatten.any? do |
|
223
|
-
first_hash_key_or_param(
|
220
|
+
@declared_params.flatten.any? do |declared_param_attr|
|
221
|
+
first_hash_key_or_param(declared_param_attr.key) == param
|
224
222
|
end
|
225
223
|
end
|
226
224
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module RequestResponse
|
@@ -26,6 +24,7 @@ module Grape
|
|
26
24
|
# define a single mime type
|
27
25
|
mime_type = content_types[new_format.to_sym]
|
28
26
|
raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
|
27
|
+
|
29
28
|
namespace_stackable(:content_types, new_format.to_sym => mime_type)
|
30
29
|
else
|
31
30
|
namespace_inheritable(:format)
|
@@ -102,14 +101,13 @@ module Grape
|
|
102
101
|
def rescue_from(*args, &block)
|
103
102
|
if args.last.is_a?(Proc)
|
104
103
|
handler = args.pop
|
105
|
-
elsif
|
104
|
+
elsif block
|
106
105
|
handler = block
|
107
106
|
end
|
108
107
|
|
109
108
|
options = args.extract_options!
|
110
|
-
if
|
111
|
-
|
112
|
-
end
|
109
|
+
raise ArgumentError, 'both :with option and block cannot be passed' if block && options.key?(:with)
|
110
|
+
|
113
111
|
handler ||= extract_with(options)
|
114
112
|
|
115
113
|
if args.include?(:all)
|
@@ -127,7 +125,7 @@ module Grape
|
|
127
125
|
:base_only_rescue_handlers
|
128
126
|
end
|
129
127
|
|
130
|
-
namespace_reverse_stackable handler_type,
|
128
|
+
namespace_reverse_stackable handler_type, args.map { |arg| [arg, handler] }.to_h
|
131
129
|
end
|
132
130
|
|
133
131
|
namespace_stackable(:rescue_options, options)
|
@@ -154,7 +152,8 @@ module Grape
|
|
154
152
|
# @param model_class [Class] The model class that will be represented.
|
155
153
|
# @option options [Class] :with The entity class that will represent the model.
|
156
154
|
def represent(model_class, options)
|
157
|
-
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with]
|
155
|
+
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with].is_a?(Class)
|
156
|
+
|
158
157
|
namespace_stackable(:representations, model_class => options[:with])
|
159
158
|
end
|
160
159
|
|
@@ -162,9 +161,11 @@ module Grape
|
|
162
161
|
|
163
162
|
def extract_with(options)
|
164
163
|
return unless options.key?(:with)
|
164
|
+
|
165
165
|
with_option = options.delete(:with)
|
166
166
|
return with_option if with_option.instance_of?(Proc)
|
167
167
|
return with_option.to_sym if with_option.instance_of?(Symbol) || with_option.instance_of?(String)
|
168
|
+
|
168
169
|
raise ArgumentError, "with: #{with_option.class}, expected Symbol, String or Proc"
|
169
170
|
end
|
170
171
|
end
|
data/lib/grape/dsl/routing.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Routing
|
@@ -38,7 +36,7 @@ module Grape
|
|
38
36
|
|
39
37
|
@versions = versions | requested_versions
|
40
38
|
|
41
|
-
if
|
39
|
+
if block
|
42
40
|
within_namespace do
|
43
41
|
namespace_inheritable(:version, requested_versions)
|
44
42
|
namespace_inheritable(:version_options, options)
|
@@ -79,6 +77,10 @@ module Grape
|
|
79
77
|
namespace_inheritable(:do_not_route_options, true)
|
80
78
|
end
|
81
79
|
|
80
|
+
def do_not_document!
|
81
|
+
namespace_inheritable(:do_not_document, true)
|
82
|
+
end
|
83
|
+
|
82
84
|
def mount(mounts, *opts)
|
83
85
|
mounts = { mounts => '/' } unless mounts.respond_to?(:each_pair)
|
84
86
|
mounts.each_pair do |app, path|
|
@@ -166,7 +168,7 @@ module Grape
|
|
166
168
|
def namespace(space = nil, options = {}, &block)
|
167
169
|
@namespace_description = nil unless instance_variable_defined?(:@namespace_description) && @namespace_description
|
168
170
|
|
169
|
-
if space ||
|
171
|
+
if space || block
|
170
172
|
within_namespace do
|
171
173
|
previous_namespace_description = @namespace_description
|
172
174
|
@namespace_description = (@namespace_description || {}).deep_merge(namespace_setting(:description) || {})
|
data/lib/grape/dsl/settings.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
# Keeps track of settings (implemented as key-value pairs, grouped by
|
@@ -103,12 +101,14 @@ module Grape
|
|
103
101
|
def namespace_stackable_with_hash(key)
|
104
102
|
settings = get_or_set :namespace_stackable, key, nil
|
105
103
|
return if settings.blank?
|
104
|
+
|
106
105
|
settings.each_with_object({}) { |value, result| result.deep_merge!(value) }
|
107
106
|
end
|
108
107
|
|
109
108
|
def namespace_reverse_stackable_with_hash(key)
|
110
109
|
settings = get_or_set :namespace_reverse_stackable, key, nil
|
111
110
|
return if settings.blank?
|
111
|
+
|
112
112
|
result = {}
|
113
113
|
settings.each do |setting|
|
114
114
|
setting.each do |field, value|
|
@@ -154,10 +154,10 @@ module Grape
|
|
154
154
|
|
155
155
|
# Execute the block within a context where our inheritable settings are forked
|
156
156
|
# to a new copy (see #namespace_start).
|
157
|
-
def within_namespace(&
|
157
|
+
def within_namespace(&block)
|
158
158
|
namespace_start
|
159
159
|
|
160
|
-
result = yield if
|
160
|
+
result = yield if block
|
161
161
|
|
162
162
|
namespace_end
|
163
163
|
reset_validations!
|
@@ -175,9 +175,7 @@ module Grape
|
|
175
175
|
# +inheritable_setting+, however, it doesn't contain any user-defined settings.
|
176
176
|
# Otherwise, it would lead to an extra instance of +Grape::Util::InheritableSetting+
|
177
177
|
# in the chain for every endpoint.
|
178
|
-
if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API::Instance
|
179
|
-
setting.inherit_from superclass.inheritable_setting
|
180
|
-
end
|
178
|
+
setting.inherit_from superclass.inheritable_setting if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API::Instance
|
181
179
|
end
|
182
180
|
end
|
183
181
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Validations
|
@@ -32,7 +30,6 @@ module Grape
|
|
32
30
|
unset_namespace_stackable :declared_params
|
33
31
|
unset_namespace_stackable :validations
|
34
32
|
unset_namespace_stackable :params
|
35
|
-
unset_description_field :params
|
36
33
|
end
|
37
34
|
|
38
35
|
# Opens a root-level ParamsScope, defining parameter coercions and
|
@@ -41,18 +38,6 @@ module Grape
|
|
41
38
|
def params(&block)
|
42
39
|
Grape::Validations::ParamsScope.new(api: self, type: Hash, &block)
|
43
40
|
end
|
44
|
-
|
45
|
-
def document_attribute(names, opts)
|
46
|
-
setting = description_field(:params)
|
47
|
-
setting ||= description_field(:params, {})
|
48
|
-
Array(names).each do |name|
|
49
|
-
full_name = name[:full_name].to_s
|
50
|
-
setting[full_name] ||= {}
|
51
|
-
setting[full_name].merge!(opts)
|
52
|
-
|
53
|
-
namespace_stackable(:params, full_name => opts)
|
54
|
-
end
|
55
|
-
end
|
56
41
|
end
|
57
42
|
end
|
58
43
|
end
|