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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +109 -0
  3. data/CONTRIBUTING.md +2 -10
  4. data/README.md +137 -181
  5. data/UPGRADING.md +154 -0
  6. data/grape.gemspec +4 -4
  7. data/lib/grape/api/instance.rb +51 -104
  8. data/lib/grape/api.rb +29 -42
  9. data/lib/grape/content_types.rb +1 -4
  10. data/lib/grape/declared_params_handler.rb +118 -0
  11. data/lib/grape/dry_types.rb +48 -4
  12. data/lib/grape/dsl/callbacks.rb +8 -58
  13. data/lib/grape/dsl/declared.rb +35 -0
  14. data/lib/grape/dsl/desc.rb +8 -67
  15. data/lib/grape/dsl/helpers.rb +59 -64
  16. data/lib/grape/dsl/inside_route.rb +28 -189
  17. data/lib/grape/dsl/logger.rb +3 -6
  18. data/lib/grape/dsl/middleware.rb +22 -40
  19. data/lib/grape/dsl/parameters.rb +24 -51
  20. data/lib/grape/dsl/request_response.rb +136 -139
  21. data/lib/grape/dsl/routing.rb +240 -200
  22. data/lib/grape/dsl/settings.rb +23 -135
  23. data/lib/grape/dsl/validations.rb +38 -44
  24. data/lib/grape/endpoint.rb +169 -205
  25. data/lib/grape/error_formatter/base.rb +4 -2
  26. data/lib/grape/exceptions/base.rb +19 -45
  27. data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
  28. data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
  29. data/lib/grape/exceptions/invalid_formatter.rb +1 -1
  30. data/lib/grape/exceptions/invalid_message_body.rb +1 -1
  31. data/lib/grape/exceptions/invalid_version_header.rb +1 -1
  32. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
  33. data/lib/grape/exceptions/method_not_allowed.rb +1 -1
  34. data/lib/grape/exceptions/missing_group_type.rb +0 -2
  35. data/lib/grape/exceptions/missing_mime_type.rb +1 -1
  36. data/lib/grape/exceptions/request_error.rb +11 -0
  37. data/lib/grape/exceptions/unknown_auth_strategy.rb +1 -1
  38. data/lib/grape/exceptions/unknown_parameter.rb +1 -1
  39. data/lib/grape/exceptions/unknown_params_builder.rb +1 -1
  40. data/lib/grape/exceptions/unknown_validator.rb +1 -1
  41. data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
  42. data/lib/grape/exceptions/validation.rb +7 -4
  43. data/lib/grape/exceptions/validation_errors.rb +13 -7
  44. data/lib/grape/locale/en.yml +0 -5
  45. data/lib/grape/middleware/auth/base.rb +2 -0
  46. data/lib/grape/middleware/auth/dsl.rb +9 -10
  47. data/lib/grape/middleware/base.rb +6 -4
  48. data/lib/grape/middleware/error.rb +4 -14
  49. data/lib/grape/middleware/formatter.rb +11 -7
  50. data/lib/grape/middleware/stack.rb +3 -2
  51. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -3
  52. data/lib/grape/middleware/versioner/base.rb +42 -40
  53. data/lib/grape/middleware/versioner/header.rb +2 -18
  54. data/lib/grape/middleware/versioner/param.rb +2 -2
  55. data/lib/grape/middleware/versioner/path.rb +2 -2
  56. data/lib/grape/namespace.rb +15 -8
  57. data/lib/grape/params_builder/base.rb +2 -0
  58. data/lib/grape/params_builder.rb +2 -19
  59. data/lib/grape/request.rb +2 -10
  60. data/lib/grape/router/base_route.rb +14 -5
  61. data/lib/grape/router/greedy_route.rb +11 -5
  62. data/lib/grape/router/pattern.rb +6 -20
  63. data/lib/grape/router/route.rb +7 -11
  64. data/lib/grape/router.rb +42 -65
  65. data/lib/grape/util/api_description.rb +58 -0
  66. data/lib/grape/util/base_inheritable.rb +5 -2
  67. data/lib/grape/util/cache.rb +1 -0
  68. data/lib/grape/util/deep_freeze.rb +35 -0
  69. data/lib/grape/util/inheritable_setting.rb +8 -1
  70. data/lib/grape/util/media_type.rb +2 -2
  71. data/lib/grape/util/registry.rb +1 -1
  72. data/lib/grape/util/translation.rb +42 -0
  73. data/lib/grape/validations/attributes_iterator.rb +35 -20
  74. data/lib/grape/validations/contract_scope.rb +2 -8
  75. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  76. data/lib/grape/validations/param_scope_tracker.rb +57 -0
  77. data/lib/grape/validations/params_documentation.rb +50 -0
  78. data/lib/grape/validations/params_scope.rb +147 -156
  79. data/lib/grape/validations/single_attribute_iterator.rb +2 -2
  80. data/lib/grape/validations/types/array_coercer.rb +2 -3
  81. data/lib/grape/validations/types/dry_type_coercer.rb +4 -11
  82. data/lib/grape/validations/types/primitive_coercer.rb +1 -28
  83. data/lib/grape/validations/types.rb +10 -25
  84. data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
  85. data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
  86. data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
  87. data/lib/grape/validations/validators/base.rb +95 -25
  88. data/lib/grape/validations/validators/coerce_validator.rb +15 -35
  89. data/lib/grape/validations/validators/contract_scope_validator.rb +9 -5
  90. data/lib/grape/validations/validators/default_validator.rb +12 -18
  91. data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
  92. data/lib/grape/validations/validators/except_values_validator.rb +13 -4
  93. data/lib/grape/validations/validators/length_validator.rb +21 -22
  94. data/lib/grape/validations/validators/multiple_params_base.rb +5 -5
  95. data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
  96. data/lib/grape/validations/validators/presence_validator.rb +4 -2
  97. data/lib/grape/validations/validators/regexp_validator.rb +11 -3
  98. data/lib/grape/validations/validators/same_as_validator.rb +6 -15
  99. data/lib/grape/validations/validators/values_validator.rb +29 -21
  100. data/lib/grape/version.rb +1 -1
  101. data/lib/grape.rb +29 -23
  102. metadata +31 -26
  103. data/lib/grape/api/helpers.rb +0 -9
  104. data/lib/grape/dsl/api.rb +0 -17
  105. data/lib/grape/dsl/configuration.rb +0 -15
  106. data/lib/grape/exceptions/conflicting_types.rb +0 -11
  107. data/lib/grape/exceptions/empty_message_body.rb +0 -11
  108. data/lib/grape/exceptions/invalid_parameters.rb +0 -11
  109. data/lib/grape/exceptions/missing_option.rb +0 -11
  110. data/lib/grape/exceptions/too_deep_parameters.rb +0 -11
  111. data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
  112. data/lib/grape/exceptions/unknown_options.rb +0 -11
  113. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -24
  114. data/lib/grape/extensions/hash.rb +0 -27
  115. data/lib/grape/extensions/hashie/mash.rb +0 -24
  116. data/lib/grape/types/invalid_value.rb +0 -8
  117. data/lib/grape/util/strict_hash_configuration.rb +0 -108
  118. data/lib/grape/validations/attributes_doc.rb +0 -60
  119. 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
@@ -2,9 +2,53 @@
2
2
 
3
3
  module Grape
4
4
  module DryTypes
5
- # Call +Dry.Types()+ to add all registered types to +DryTypes+ which is
6
- # a container in this case. Check documentation for more information
7
- # https://dry-rb.org/gems/dry-types/1.2/getting-started/
8
- include Dry.Types()
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
@@ -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
- extend ActiveSupport::Concern
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
- include Grape::DSL::Configuration
22
-
23
- module ClassMethods
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
@@ -3,28 +3,7 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Desc
6
- include Grape::DSL::Settings
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 = nil, &config_block)
74
- opts =
52
+ def desc(description, options = {}, &config_block)
53
+ settings =
75
54
  if config_block
76
- desc_container(endpoint_configuration).then do |config_class|
77
- config_class.configure do
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&.merge(description: description) || { description: description }
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
- end
108
- end
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
@@ -3,81 +3,76 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Helpers
6
- extend ActiveSupport::Concern
7
- include Grape::DSL::Configuration
8
-
9
- module ClassMethods
10
- # Add helper methods that will be accessible from any
11
- # endpoint within this namespace (and child namespaces).
12
- #
13
- # When called without a block, all known helpers within this scope
14
- # are included.
15
- #
16
- # @param [Array] new_modules optional array of modules to include
17
- # @param [Block] block optional block of methods to include
18
- #
19
- # @example Define some helpers.
20
- #
21
- # class ExampleAPI < Grape::API
22
- # helpers do
23
- # def current_user
24
- # User.find_by_id(params[:token])
25
- # end
26
- # end
27
- # end
28
- #
29
- # @example Include many modules
30
- #
31
- # class ExampleAPI < Grape::API
32
- # helpers Authentication, Mailer, OtherModule
33
- # end
34
- #
35
- def helpers(*new_modules, &block)
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
- protected
37
+ private
42
38
 
43
- def include_new_modules(modules)
44
- return if modules.empty?
39
+ def include_new_modules(modules)
40
+ return if modules.empty?
45
41
 
46
- modules.each { |mod| make_inclusion(mod) }
47
- end
42
+ modules.each { |mod| make_inclusion(mod) }
43
+ end
48
44
 
49
- def include_block(block)
50
- return unless block
45
+ def include_block(block)
46
+ return unless block
51
47
 
52
- Module.new.tap do |mod|
53
- make_inclusion(mod) { mod.class_eval(&block) }
54
- end
48
+ Module.new.tap do |mod|
49
+ make_inclusion(mod) { mod.class_eval(&block) }
55
50
  end
51
+ end
56
52
 
57
- def make_inclusion(mod, &block)
58
- define_boolean_in_mod(mod)
59
- inject_api_helpers_to_mod(mod, &block)
60
- namespace_stackable(:helpers, mod)
61
- end
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
- def include_all_in_scope
64
- Module.new.tap do |mod|
65
- namespace_stackable(:helpers).each { |mod_to_include| mod.include mod_to_include }
66
- change!
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
- def define_boolean_in_mod(mod)
71
- return if defined? mod::Boolean
66
+ def define_boolean_in_mod(mod)
67
+ return if defined? mod::Boolean
72
68
 
73
- mod.const_set(:Boolean, Grape::API::Boolean)
74
- end
69
+ mod.const_set(:Boolean, Grape::API::Boolean)
70
+ end
75
71
 
76
- def inject_api_helpers_to_mod(mod, &block)
77
- mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
78
- yield if block
79
- mod.api_changed(self)
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(:named_params, @named_params)
98
+ api.inheritable_setting.namespace_stackable[:named_params] = @named_params
104
99
  end
105
100
  end
106
101
  end