grape 2.4.0 → 3.2.1
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 +109 -0
- data/CONTRIBUTING.md +2 -10
- data/README.md +137 -181
- data/UPGRADING.md +154 -0
- data/grape.gemspec +4 -4
- data/lib/grape/api/instance.rb +51 -104
- data/lib/grape/api.rb +29 -42
- data/lib/grape/content_types.rb +1 -4
- data/lib/grape/declared_params_handler.rb +118 -0
- data/lib/grape/dry_types.rb +48 -4
- data/lib/grape/dsl/callbacks.rb +8 -58
- data/lib/grape/dsl/declared.rb +35 -0
- data/lib/grape/dsl/desc.rb +8 -67
- data/lib/grape/dsl/helpers.rb +59 -64
- data/lib/grape/dsl/inside_route.rb +28 -189
- data/lib/grape/dsl/logger.rb +3 -6
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +24 -51
- data/lib/grape/dsl/request_response.rb +136 -139
- data/lib/grape/dsl/routing.rb +240 -200
- data/lib/grape/dsl/settings.rb +23 -135
- data/lib/grape/dsl/validations.rb +38 -44
- data/lib/grape/endpoint.rb +169 -205
- data/lib/grape/error_formatter/base.rb +4 -2
- data/lib/grape/exceptions/base.rb +19 -45
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_message_body.rb +1 -1
- data/lib/grape/exceptions/invalid_version_header.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/method_not_allowed.rb +1 -1
- data/lib/grape/exceptions/missing_group_type.rb +0 -2
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/request_error.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +1 -1
- data/lib/grape/exceptions/unknown_parameter.rb +1 -1
- data/lib/grape/exceptions/unknown_params_builder.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
- data/lib/grape/exceptions/validation.rb +7 -4
- data/lib/grape/exceptions/validation_errors.rb +13 -7
- data/lib/grape/locale/en.yml +0 -5
- data/lib/grape/middleware/auth/base.rb +2 -0
- data/lib/grape/middleware/auth/dsl.rb +9 -10
- data/lib/grape/middleware/base.rb +6 -4
- data/lib/grape/middleware/error.rb +4 -14
- data/lib/grape/middleware/formatter.rb +11 -7
- data/lib/grape/middleware/stack.rb +3 -2
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -3
- data/lib/grape/middleware/versioner/base.rb +42 -40
- data/lib/grape/middleware/versioner/header.rb +2 -18
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +2 -2
- data/lib/grape/namespace.rb +15 -8
- data/lib/grape/params_builder/base.rb +2 -0
- data/lib/grape/params_builder.rb +2 -19
- data/lib/grape/request.rb +2 -10
- data/lib/grape/router/base_route.rb +14 -5
- data/lib/grape/router/greedy_route.rb +11 -5
- data/lib/grape/router/pattern.rb +6 -20
- data/lib/grape/router/route.rb +7 -11
- data/lib/grape/router.rb +42 -65
- data/lib/grape/util/api_description.rb +58 -0
- data/lib/grape/util/base_inheritable.rb +5 -2
- data/lib/grape/util/cache.rb +1 -0
- data/lib/grape/util/deep_freeze.rb +35 -0
- data/lib/grape/util/inheritable_setting.rb +8 -1
- data/lib/grape/util/media_type.rb +2 -2
- data/lib/grape/util/registry.rb +1 -1
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +35 -20
- data/lib/grape/validations/contract_scope.rb +2 -8
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/param_scope_tracker.rb +57 -0
- data/lib/grape/validations/params_documentation.rb +50 -0
- data/lib/grape/validations/params_scope.rb +147 -156
- data/lib/grape/validations/single_attribute_iterator.rb +2 -2
- data/lib/grape/validations/types/array_coercer.rb +2 -3
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -11
- data/lib/grape/validations/types/primitive_coercer.rb +1 -28
- data/lib/grape/validations/types.rb +10 -25
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
- data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
- data/lib/grape/validations/validators/base.rb +95 -25
- data/lib/grape/validations/validators/coerce_validator.rb +15 -35
- data/lib/grape/validations/validators/contract_scope_validator.rb +9 -5
- data/lib/grape/validations/validators/default_validator.rb +12 -18
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +13 -4
- data/lib/grape/validations/validators/length_validator.rb +21 -22
- data/lib/grape/validations/validators/multiple_params_base.rb +5 -5
- data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +11 -3
- data/lib/grape/validations/validators/same_as_validator.rb +6 -15
- data/lib/grape/validations/validators/values_validator.rb +29 -21
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +29 -23
- metadata +31 -26
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -17
- data/lib/grape/dsl/configuration.rb +0 -15
- data/lib/grape/exceptions/conflicting_types.rb +0 -11
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/invalid_parameters.rb +0 -11
- data/lib/grape/exceptions/missing_option.rb +0 -11
- data/lib/grape/exceptions/too_deep_parameters.rb +0 -11
- data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
- data/lib/grape/exceptions/unknown_options.rb +0 -11
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -24
- data/lib/grape/extensions/hash.rb +0 -27
- data/lib/grape/extensions/hashie/mash.rb +0 -24
- data/lib/grape/types/invalid_value.rb +0 -8
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/validations/attributes_doc.rb +0 -60
- data/lib/grape/validations/validator_factory.rb +0 -15
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
class DeclaredParamsHandler
|
|
5
|
+
def initialize(include_missing: true, evaluate_given: false, stringify: false, contract_key_map: nil)
|
|
6
|
+
@include_missing = include_missing
|
|
7
|
+
@evaluate_given = evaluate_given
|
|
8
|
+
@stringify = stringify
|
|
9
|
+
@contract_key_map = contract_key_map
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(passed_params, declared_params, route_params, renamed_params)
|
|
13
|
+
recursive_declared(
|
|
14
|
+
passed_params,
|
|
15
|
+
declared_params:,
|
|
16
|
+
route_params:,
|
|
17
|
+
renamed_params:
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def recursive_declared(passed_params, declared_params:, route_params:, renamed_params:, params_nested_path: [])
|
|
24
|
+
res = if passed_params.is_a?(Array)
|
|
25
|
+
passed_params.map do |passed_param|
|
|
26
|
+
recursive_declared(passed_param, declared_params:, params_nested_path:, renamed_params:, route_params:)
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
declared_hash(passed_params, declared_params:, params_nested_path:, renamed_params:, route_params:)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
@contract_key_map&.each { |key_map| key_map.write(passed_params, res) }
|
|
33
|
+
|
|
34
|
+
res
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def declared_hash(passed_params, declared_params:, params_nested_path:, renamed_params:, route_params:)
|
|
38
|
+
declared_params.each_with_object(passed_params.class.new) do |declared_param_attr, memo|
|
|
39
|
+
next if @evaluate_given && !declared_param_attr.scope.attr_meets_dependency?(passed_params)
|
|
40
|
+
|
|
41
|
+
declared_hash_attr(
|
|
42
|
+
passed_params,
|
|
43
|
+
declared_param: declared_param_attr.key,
|
|
44
|
+
params_nested_path:,
|
|
45
|
+
memo:,
|
|
46
|
+
renamed_params:,
|
|
47
|
+
route_params:
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def declared_hash_attr(passed_params, declared_param:, params_nested_path:, memo:, renamed_params:, route_params:)
|
|
53
|
+
if declared_param.is_a?(Hash)
|
|
54
|
+
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
|
55
|
+
next unless @include_missing || passed_params.key?(declared_parent_param)
|
|
56
|
+
|
|
57
|
+
memo_key = build_memo_key(params_nested_path, declared_parent_param, renamed_params)
|
|
58
|
+
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
|
|
59
|
+
|
|
60
|
+
params_nested_path_dup = params_nested_path.dup
|
|
61
|
+
params_nested_path_dup << declared_parent_param.to_s
|
|
62
|
+
|
|
63
|
+
memo[memo_key] = handle_passed_param(params_nested_path_dup, route_params:, has_passed_children: passed_children_params.any?) do
|
|
64
|
+
recursive_declared(
|
|
65
|
+
passed_children_params,
|
|
66
|
+
declared_params: declared_children_params,
|
|
67
|
+
params_nested_path: params_nested_path_dup,
|
|
68
|
+
renamed_params:,
|
|
69
|
+
route_params:
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
else
|
|
74
|
+
# If it is not a Hash then it does not have children.
|
|
75
|
+
# Find its value or set it to nil.
|
|
76
|
+
return unless @include_missing || (passed_params.respond_to?(:key?) && passed_params.key?(declared_param))
|
|
77
|
+
|
|
78
|
+
memo_key = build_memo_key(params_nested_path, declared_param, renamed_params)
|
|
79
|
+
passed_param = passed_params[declared_param]
|
|
80
|
+
|
|
81
|
+
params_nested_path_dup = params_nested_path.dup
|
|
82
|
+
params_nested_path_dup << declared_param.to_s
|
|
83
|
+
|
|
84
|
+
memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup, route_params:) do
|
|
85
|
+
passed_param
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def build_memo_key(params_nested_path, declared_param, renamed_params)
|
|
91
|
+
rename_path = params_nested_path + [declared_param.to_s]
|
|
92
|
+
renamed_param_name = renamed_params[rename_path]
|
|
93
|
+
|
|
94
|
+
param = renamed_param_name || declared_param
|
|
95
|
+
@stringify ? param.to_s : param.to_sym
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def handle_passed_param(params_nested_path, route_params:, has_passed_children: false, &_block)
|
|
99
|
+
return yield if has_passed_children
|
|
100
|
+
|
|
101
|
+
key = params_nested_path[0]
|
|
102
|
+
key += "[#{params_nested_path[1..].join('][')}]" if params_nested_path.size > 1
|
|
103
|
+
|
|
104
|
+
type = route_params.dig(key, :type)
|
|
105
|
+
has_children = route_params.keys.any? { |k| k != key && k.start_with?("#{key}[") }
|
|
106
|
+
|
|
107
|
+
if type == 'Hash' && !has_children
|
|
108
|
+
{}
|
|
109
|
+
elsif type == 'Array' || (type&.start_with?('[') && !type.include?(','))
|
|
110
|
+
[]
|
|
111
|
+
elsif type == 'Set' || type&.start_with?('#<Set', 'Set')
|
|
112
|
+
Set.new
|
|
113
|
+
else
|
|
114
|
+
yield
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
data/lib/grape/dry_types.rb
CHANGED
|
@@ -2,9 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DryTypes
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
# https://dry-rb.org/gems/dry-types/main/getting-started/
|
|
6
|
+
# limit to what Grape is using
|
|
7
|
+
include Dry.Types(:params, :coercible, :strict)
|
|
8
|
+
|
|
9
|
+
class StrictCache < Grape::Util::Cache
|
|
10
|
+
MAPPING = {
|
|
11
|
+
Grape::API::Boolean => DryTypes::Strict::Bool,
|
|
12
|
+
BigDecimal => DryTypes::Strict::Decimal,
|
|
13
|
+
Numeric => DryTypes::Strict::Integer | DryTypes::Strict::Float | DryTypes::Strict::Decimal,
|
|
14
|
+
TrueClass => DryTypes::Strict::Bool.constrained(eql: true),
|
|
15
|
+
FalseClass => DryTypes::Strict::Bool.constrained(eql: false)
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
super
|
|
20
|
+
@cache = Hash.new do |h, strict_type|
|
|
21
|
+
h[strict_type] = MAPPING.fetch(strict_type) do
|
|
22
|
+
DryTypes.wrapped_dry_types_const_get(DryTypes::Strict, strict_type)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class ParamsCache < Grape::Util::Cache
|
|
29
|
+
MAPPING = {
|
|
30
|
+
Grape::API::Boolean => DryTypes::Params::Bool,
|
|
31
|
+
BigDecimal => DryTypes::Params::Decimal,
|
|
32
|
+
Numeric => DryTypes::Params::Integer | DryTypes::Params::Float | DryTypes::Params::Decimal,
|
|
33
|
+
TrueClass => DryTypes::Params::Bool.constrained(eql: true),
|
|
34
|
+
FalseClass => DryTypes::Params::Bool.constrained(eql: false),
|
|
35
|
+
String => DryTypes::Coercible::String
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
def initialize
|
|
39
|
+
super
|
|
40
|
+
@cache = Hash.new do |h, params_type|
|
|
41
|
+
h[params_type] = MAPPING.fetch(params_type) do
|
|
42
|
+
DryTypes.wrapped_dry_types_const_get(DryTypes::Params, params_type)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.wrapped_dry_types_const_get(dry_type, type)
|
|
49
|
+
dry_type.const_get(type.name, false)
|
|
50
|
+
rescue NameError
|
|
51
|
+
raise ArgumentError, "type #{type} should support coercion via `[]`" unless type.respond_to?(:[])
|
|
52
|
+
end
|
|
9
53
|
end
|
|
10
54
|
end
|
data/lib/grape/dsl/callbacks.rb
CHANGED
|
@@ -2,66 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
|
-
# Blocks can be executed before or after every API call, using `before`, `after`,
|
|
6
|
-
# `before_validation` and `after_validation`.
|
|
7
|
-
#
|
|
8
|
-
# Before and after callbacks execute in the following order:
|
|
9
|
-
#
|
|
10
|
-
# 1. `before`
|
|
11
|
-
# 2. `before_validation`
|
|
12
|
-
# 3. _validations_
|
|
13
|
-
# 4. `after_validation`
|
|
14
|
-
# 5. _the API call_
|
|
15
|
-
# 6. `after`
|
|
16
|
-
#
|
|
17
|
-
# Steps 4, 5 and 6 only happen if validation succeeds.
|
|
18
5
|
module Callbacks
|
|
19
|
-
|
|
6
|
+
# before: execute the given block before validation, coercion, or any endpoint
|
|
7
|
+
# before_validation: execute the given block after `before`, but prior to validation or coercion
|
|
8
|
+
# after_validation: execute the given block after validations and coercions, but before any endpoint code
|
|
9
|
+
# after: execute the given block after the endpoint code has run except in unsuccessful
|
|
10
|
+
# finally: execute the given block after the endpoint code even if unsuccessful
|
|
20
11
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Execute the given block before validation, coercion, or any endpoint
|
|
25
|
-
# code is executed.
|
|
26
|
-
def before(&block)
|
|
27
|
-
namespace_stackable(:befores, block)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Execute the given block after `before`, but prior to validation or
|
|
31
|
-
# coercion.
|
|
32
|
-
def before_validation(&block)
|
|
33
|
-
namespace_stackable(:before_validations, block)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Execute the given block after validations and coercions, but before
|
|
37
|
-
# any endpoint code.
|
|
38
|
-
def after_validation(&block)
|
|
39
|
-
namespace_stackable(:after_validations, block)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Execute the given block after the endpoint code has run.
|
|
43
|
-
def after(&block)
|
|
44
|
-
namespace_stackable(:afters, block)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Allows you to specify a something that will always be executed after a call
|
|
48
|
-
# API call. Unlike the `after` block, this code will run even on
|
|
49
|
-
# unsuccesful requests.
|
|
50
|
-
# @example
|
|
51
|
-
# class ExampleAPI < Grape::API
|
|
52
|
-
# before do
|
|
53
|
-
# ApiLogger.start
|
|
54
|
-
# end
|
|
55
|
-
# finally do
|
|
56
|
-
# ApiLogger.close
|
|
57
|
-
# end
|
|
58
|
-
# end
|
|
59
|
-
#
|
|
60
|
-
# This will make sure that the ApiLogger is opened and closed around every
|
|
61
|
-
# request
|
|
62
|
-
# @param ensured_block [Proc] The block to be executed after every api_call
|
|
63
|
-
def finally(&block)
|
|
64
|
-
namespace_stackable(:finallies, block)
|
|
12
|
+
%w[before before_validation after_validation after finally].each do |callback_method|
|
|
13
|
+
define_method callback_method.to_sym do |&block|
|
|
14
|
+
inheritable_setting.namespace_stackable[callback_method.pluralize.to_sym] = block
|
|
65
15
|
end
|
|
66
16
|
end
|
|
67
17
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module DSL
|
|
5
|
+
module Declared
|
|
6
|
+
# Denotes a situation where a DSL method has been invoked in a
|
|
7
|
+
# filter which it should not yet be available in
|
|
8
|
+
class MethodNotYetAvailable < StandardError
|
|
9
|
+
def initialize(msg = '#declared is not available prior to parameter validation')
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# A filtering method that will return a hash
|
|
15
|
+
# consisting only of keys that have been declared by a
|
|
16
|
+
# `params` statement against the current/target endpoint or parent
|
|
17
|
+
# namespaces.
|
|
18
|
+
# @param params [Hash] The initial hash to filter. Usually this will just be `params`
|
|
19
|
+
# @param options [Hash] Can pass `:include_missing`, `:stringify` and `:include_parent_namespaces`
|
|
20
|
+
# options. `:include_parent_namespaces` defaults to true, hence must be set to false if
|
|
21
|
+
# you want only to return params declared against the current/target endpoint.
|
|
22
|
+
def declared(passed_params, include_parent_namespaces: true, include_missing: true, evaluate_given: false, stringify: false)
|
|
23
|
+
raise MethodNotYetAvailable unless before_filter_passed
|
|
24
|
+
|
|
25
|
+
contract_key_map = inheritable_setting.namespace_stackable[:contract_key_map]
|
|
26
|
+
handler = DeclaredParamsHandler.new(include_missing:, evaluate_given:, stringify:, contract_key_map:)
|
|
27
|
+
declared_params = include_parent_namespaces ? inheritable_setting.route[:declared_params] : (inheritable_setting.namespace_stackable[:declared_params].last || [])
|
|
28
|
+
renamed_params = inheritable_setting.route[:renamed_params] || {}
|
|
29
|
+
route_params = options.dig(:route_options, :params) || {} # options = endpoint's option
|
|
30
|
+
|
|
31
|
+
handler.call(passed_params, declared_params, route_params, renamed_params)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/grape/dsl/desc.rb
CHANGED
|
@@ -3,28 +3,7 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Desc
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ROUTE_ATTRIBUTES = %i[
|
|
9
|
-
body_name
|
|
10
|
-
consumes
|
|
11
|
-
default
|
|
12
|
-
deprecated
|
|
13
|
-
description
|
|
14
|
-
detail
|
|
15
|
-
entity
|
|
16
|
-
headers
|
|
17
|
-
hidden
|
|
18
|
-
http_codes
|
|
19
|
-
is_array
|
|
20
|
-
named
|
|
21
|
-
nickname
|
|
22
|
-
params
|
|
23
|
-
produces
|
|
24
|
-
security
|
|
25
|
-
summary
|
|
26
|
-
tags
|
|
27
|
-
].freeze
|
|
6
|
+
extend Grape::DSL::Settings
|
|
28
7
|
|
|
29
8
|
# Add a description to the next namespace or function.
|
|
30
9
|
# @param description [String] descriptive string for this endpoint
|
|
@@ -70,54 +49,16 @@ module Grape
|
|
|
70
49
|
# # ...
|
|
71
50
|
# end
|
|
72
51
|
#
|
|
73
|
-
def desc(description, options =
|
|
74
|
-
|
|
52
|
+
def desc(description, options = {}, &config_block)
|
|
53
|
+
settings =
|
|
75
54
|
if config_block
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
description(description)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
config_class.configure(&config_block)
|
|
82
|
-
config_class.settings
|
|
83
|
-
end
|
|
55
|
+
endpoint_config = defined?(configuration) ? configuration : nil
|
|
56
|
+
Grape::Util::ApiDescription.new(description, endpoint_config, &config_block).settings
|
|
84
57
|
else
|
|
85
|
-
options
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
namespace_setting :description, opts
|
|
89
|
-
route_setting :description, opts
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Returns an object which configures itself via an instance-context DSL.
|
|
93
|
-
def desc_container(endpoint_configuration)
|
|
94
|
-
Module.new do
|
|
95
|
-
include Grape::Util::StrictHashConfiguration.module(*ROUTE_ATTRIBUTES)
|
|
96
|
-
config_context.define_singleton_method(:configuration) do
|
|
97
|
-
endpoint_configuration
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def config_context.success(*args)
|
|
101
|
-
entity(*args)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def config_context.failure(*args)
|
|
105
|
-
http_codes(*args)
|
|
58
|
+
options.merge(description:)
|
|
106
59
|
end
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
def endpoint_configuration
|
|
113
|
-
return {} unless defined?(configuration)
|
|
114
|
-
|
|
115
|
-
if configuration.respond_to?(:evaluate)
|
|
116
|
-
configuration.evaluate
|
|
117
|
-
# Within `given` or `mounted blocks` the configuration is already evaluated
|
|
118
|
-
elsif configuration.is_a?(Hash)
|
|
119
|
-
configuration
|
|
120
|
-
end
|
|
60
|
+
inheritable_setting.namespace[:description] = settings
|
|
61
|
+
inheritable_setting.route[:description] = settings
|
|
121
62
|
end
|
|
122
63
|
end
|
|
123
64
|
end
|
data/lib/grape/dsl/helpers.rb
CHANGED
|
@@ -3,81 +3,76 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Helpers
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
include_new_modules(new_modules)
|
|
37
|
-
include_block(block)
|
|
38
|
-
include_all_in_scope if !block && new_modules.empty?
|
|
39
|
-
end
|
|
6
|
+
# Add helper methods that will be accessible from any
|
|
7
|
+
# endpoint within this namespace (and child namespaces).
|
|
8
|
+
#
|
|
9
|
+
# When called without a block, all known helpers within this scope
|
|
10
|
+
# are included.
|
|
11
|
+
#
|
|
12
|
+
# @param [Array] new_modules optional array of modules to include
|
|
13
|
+
# @param [Block] block optional block of methods to include
|
|
14
|
+
#
|
|
15
|
+
# @example Define some helpers.
|
|
16
|
+
#
|
|
17
|
+
# class ExampleAPI < Grape::API
|
|
18
|
+
# helpers do
|
|
19
|
+
# def current_user
|
|
20
|
+
# User.find_by_id(params[:token])
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# @example Include many modules
|
|
26
|
+
#
|
|
27
|
+
# class ExampleAPI < Grape::API
|
|
28
|
+
# helpers Authentication, Mailer, OtherModule
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
def helpers(*new_modules, &block)
|
|
32
|
+
include_new_modules(new_modules)
|
|
33
|
+
include_block(block)
|
|
34
|
+
include_all_in_scope if !block && new_modules.empty?
|
|
35
|
+
end
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
private
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
def include_new_modules(modules)
|
|
40
|
+
return if modules.empty?
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
modules.each { |mod| make_inclusion(mod) }
|
|
43
|
+
end
|
|
48
44
|
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
def include_block(block)
|
|
46
|
+
return unless block
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
end
|
|
48
|
+
Module.new.tap do |mod|
|
|
49
|
+
make_inclusion(mod) { mod.class_eval(&block) }
|
|
55
50
|
end
|
|
51
|
+
end
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
def make_inclusion(mod, &)
|
|
54
|
+
define_boolean_in_mod(mod)
|
|
55
|
+
inject_api_helpers_to_mod(mod, &)
|
|
56
|
+
inheritable_setting.namespace_stackable[:helpers] = mod
|
|
57
|
+
end
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
end
|
|
59
|
+
def include_all_in_scope
|
|
60
|
+
Module.new.tap do |mod|
|
|
61
|
+
namespace_stackable(:helpers).each { |mod_to_include| mod.include mod_to_include }
|
|
62
|
+
change!
|
|
68
63
|
end
|
|
64
|
+
end
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
def define_boolean_in_mod(mod)
|
|
67
|
+
return if defined? mod::Boolean
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
mod.const_set(:Boolean, Grape::API::Boolean)
|
|
70
|
+
end
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
end
|
|
72
|
+
def inject_api_helpers_to_mod(mod, &block)
|
|
73
|
+
mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
|
|
74
|
+
yield if block
|
|
75
|
+
mod.api_changed(self)
|
|
81
76
|
end
|
|
82
77
|
|
|
83
78
|
# This module extends user defined helpers
|
|
@@ -100,7 +95,7 @@ module Grape
|
|
|
100
95
|
def process_named_params
|
|
101
96
|
return if @named_params.blank?
|
|
102
97
|
|
|
103
|
-
api.namespace_stackable
|
|
98
|
+
api.inheritable_setting.namespace_stackable[:named_params] = @named_params
|
|
104
99
|
end
|
|
105
100
|
end
|
|
106
101
|
end
|