grape 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -66
  3. data/.rubocop_todo.yml +78 -17
  4. data/.travis.yml +7 -3
  5. data/Appraisals +7 -0
  6. data/CHANGELOG.md +24 -0
  7. data/CONTRIBUTING.md +7 -0
  8. data/Gemfile +1 -7
  9. data/Guardfile +1 -1
  10. data/README.md +560 -94
  11. data/RELEASING.md +1 -1
  12. data/Rakefile +10 -11
  13. data/UPGRADING.md +211 -3
  14. data/gemfiles/rails_3.gemfile +14 -0
  15. data/gemfiles/rails_4.gemfile +14 -0
  16. data/grape.gemspec +10 -9
  17. data/lib/backports/active_support/deep_dup.rb +49 -0
  18. data/lib/backports/active_support/duplicable.rb +88 -0
  19. data/lib/grape.rb +29 -2
  20. data/lib/grape/api.rb +59 -65
  21. data/lib/grape/dsl/api.rb +19 -0
  22. data/lib/grape/dsl/callbacks.rb +6 -4
  23. data/lib/grape/dsl/configuration.rb +49 -5
  24. data/lib/grape/dsl/helpers.rb +7 -8
  25. data/lib/grape/dsl/inside_route.rb +22 -10
  26. data/lib/grape/dsl/middleware.rb +5 -5
  27. data/lib/grape/dsl/parameters.rb +6 -2
  28. data/lib/grape/dsl/request_response.rb +23 -20
  29. data/lib/grape/dsl/routing.rb +52 -49
  30. data/lib/grape/dsl/settings.rb +110 -0
  31. data/lib/grape/dsl/validations.rb +14 -6
  32. data/lib/grape/endpoint.rb +104 -88
  33. data/lib/grape/exceptions/base.rb +2 -2
  34. data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
  35. data/lib/grape/exceptions/invalid_formatter.rb +1 -1
  36. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
  37. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -1
  38. data/lib/grape/exceptions/missing_mime_type.rb +1 -1
  39. data/lib/grape/exceptions/missing_option.rb +1 -1
  40. data/lib/grape/exceptions/missing_vendor_option.rb +1 -1
  41. data/lib/grape/exceptions/unknown_options.rb +1 -1
  42. data/lib/grape/exceptions/unknown_validator.rb +1 -1
  43. data/lib/grape/exceptions/validation.rb +1 -1
  44. data/lib/grape/exceptions/validation_errors.rb +2 -2
  45. data/lib/grape/formatter/serializable_hash.rb +1 -1
  46. data/lib/grape/formatter/xml.rb +1 -1
  47. data/lib/grape/locale/en.yml +2 -0
  48. data/lib/grape/middleware/auth/dsl.rb +26 -21
  49. data/lib/grape/middleware/auth/strategies.rb +1 -1
  50. data/lib/grape/middleware/auth/strategy_info.rb +0 -2
  51. data/lib/grape/middleware/base.rb +2 -2
  52. data/lib/grape/middleware/error.rb +1 -1
  53. data/lib/grape/middleware/formatter.rb +5 -5
  54. data/lib/grape/middleware/versioner.rb +1 -1
  55. data/lib/grape/middleware/versioner/header.rb +3 -3
  56. data/lib/grape/middleware/versioner/param.rb +2 -2
  57. data/lib/grape/middleware/versioner/path.rb +1 -1
  58. data/lib/grape/namespace.rb +1 -1
  59. data/lib/grape/path.rb +9 -3
  60. data/lib/grape/util/content_types.rb +16 -8
  61. data/lib/grape/util/inheritable_setting.rb +74 -0
  62. data/lib/grape/util/inheritable_values.rb +51 -0
  63. data/lib/grape/util/stackable_values.rb +52 -0
  64. data/lib/grape/util/strict_hash_configuration.rb +106 -0
  65. data/lib/grape/validations.rb +0 -220
  66. data/lib/grape/validations/attributes_iterator.rb +21 -0
  67. data/lib/grape/validations/params_scope.rb +176 -0
  68. data/lib/grape/validations/validators/all_or_none.rb +20 -0
  69. data/lib/grape/validations/validators/allow_blank.rb +30 -0
  70. data/lib/grape/validations/validators/at_least_one_of.rb +20 -0
  71. data/lib/grape/validations/validators/base.rb +37 -0
  72. data/lib/grape/validations/{coerce.rb → validators/coerce.rb} +3 -3
  73. data/lib/grape/validations/{default.rb → validators/default.rb} +1 -1
  74. data/lib/grape/validations/validators/exactly_one_of.rb +20 -0
  75. data/lib/grape/validations/validators/multiple_params_base.rb +26 -0
  76. data/lib/grape/validations/validators/mutual_exclusion.rb +25 -0
  77. data/lib/grape/validations/{presence.rb → validators/presence.rb} +2 -2
  78. data/lib/grape/validations/validators/regexp.rb +12 -0
  79. data/lib/grape/validations/validators/values.rb +26 -0
  80. data/lib/grape/version.rb +1 -1
  81. data/spec/grape/api_spec.rb +522 -343
  82. data/spec/grape/dsl/callbacks_spec.rb +4 -4
  83. data/spec/grape/dsl/configuration_spec.rb +48 -9
  84. data/spec/grape/dsl/helpers_spec.rb +6 -13
  85. data/spec/grape/dsl/inside_route_spec.rb +43 -4
  86. data/spec/grape/dsl/middleware_spec.rb +1 -10
  87. data/spec/grape/dsl/parameters_spec.rb +8 -1
  88. data/spec/grape/dsl/request_response_spec.rb +16 -22
  89. data/spec/grape/dsl/routing_spec.rb +21 -5
  90. data/spec/grape/dsl/settings_spec.rb +219 -0
  91. data/spec/grape/dsl/validations_spec.rb +8 -11
  92. data/spec/grape/endpoint_spec.rb +115 -86
  93. data/spec/grape/entity_spec.rb +33 -33
  94. data/spec/grape/exceptions/invalid_formatter_spec.rb +3 -5
  95. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +4 -6
  96. data/spec/grape/exceptions/missing_mime_type_spec.rb +5 -6
  97. data/spec/grape/exceptions/missing_option_spec.rb +3 -5
  98. data/spec/grape/exceptions/unknown_options_spec.rb +3 -5
  99. data/spec/grape/exceptions/unknown_validator_spec.rb +3 -5
  100. data/spec/grape/exceptions/validation_errors_spec.rb +5 -5
  101. data/spec/grape/loading_spec.rb +44 -0
  102. data/spec/grape/middleware/auth/base_spec.rb +0 -4
  103. data/spec/grape/middleware/auth/dsl_spec.rb +2 -4
  104. data/spec/grape/middleware/auth/strategies_spec.rb +5 -6
  105. data/spec/grape/middleware/exception_spec.rb +8 -10
  106. data/spec/grape/middleware/formatter_spec.rb +13 -15
  107. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +10 -10
  108. data/spec/grape/middleware/versioner/header_spec.rb +25 -25
  109. data/spec/grape/middleware/versioner/param_spec.rb +15 -17
  110. data/spec/grape/middleware/versioner/path_spec.rb +1 -2
  111. data/spec/grape/middleware/versioner_spec.rb +0 -1
  112. data/spec/grape/path_spec.rb +66 -45
  113. data/spec/grape/util/inheritable_setting_spec.rb +217 -0
  114. data/spec/grape/util/inheritable_values_spec.rb +63 -0
  115. data/spec/grape/util/stackable_values_spec.rb +115 -0
  116. data/spec/grape/util/strict_hash_configuration_spec.rb +38 -0
  117. data/spec/grape/validations/attributes_iterator_spec.rb +4 -0
  118. data/spec/grape/validations/params_scope_spec.rb +57 -0
  119. data/spec/grape/validations/validators/all_or_none_spec.rb +60 -0
  120. data/spec/grape/validations/validators/allow_blank_spec.rb +170 -0
  121. data/spec/grape/validations/{at_least_one_of_spec.rb → validators/at_least_one_of_spec.rb} +7 -3
  122. data/spec/grape/validations/{coerce_spec.rb → validators/coerce_spec.rb} +8 -11
  123. data/spec/grape/validations/{default_spec.rb → validators/default_spec.rb} +7 -9
  124. data/spec/grape/validations/{exactly_one_of_spec.rb → validators/exactly_one_of_spec.rb} +15 -11
  125. data/spec/grape/validations/{mutual_exclusion_spec.rb → validators/mutual_exclusion_spec.rb} +11 -9
  126. data/spec/grape/validations/{presence_spec.rb → validators/presence_spec.rb} +30 -30
  127. data/spec/grape/validations/{regexp_spec.rb → validators/regexp_spec.rb} +2 -4
  128. data/spec/grape/validations/{values_spec.rb → validators/values_spec.rb} +95 -23
  129. data/spec/grape/validations/{zh-CN.yml → validators/zh-CN.yml} +0 -0
  130. data/spec/grape/validations_spec.rb +335 -70
  131. data/spec/shared/versioning_examples.rb +7 -8
  132. data/spec/spec_helper.rb +2 -0
  133. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  134. data/spec/support/content_type_helpers.rb +1 -1
  135. data/spec/support/versioned_helpers.rb +3 -3
  136. metadata +80 -33
  137. data/lib/grape/util/deep_merge.rb +0 -23
  138. data/lib/grape/util/hash_stack.rb +0 -120
  139. data/lib/grape/validations/at_least_one_of.rb +0 -25
  140. data/lib/grape/validations/exactly_one_of.rb +0 -26
  141. data/lib/grape/validations/mutual_exclusion.rb +0 -25
  142. data/lib/grape/validations/regexp.rb +0 -12
  143. data/lib/grape/validations/values.rb +0 -23
  144. data/spec/grape/util/hash_stack_spec.rb +0 -132
@@ -5,6 +5,8 @@ module Grape
5
5
  module Middleware
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ include Grape::DSL::Configuration
9
+
8
10
  module ClassMethods
9
11
  # Apply a custom middleware to the API. Applies
10
12
  # to the current namespace and any children, but
@@ -15,17 +17,15 @@ module Grape
15
17
  def use(middleware_class, *args, &block)
16
18
  arr = [middleware_class, *args]
17
19
  arr << block if block_given?
18
- imbue(:middleware, [arr])
20
+
21
+ namespace_stackable(:middleware, arr)
19
22
  end
20
23
 
21
24
  # Retrieve an array of the middleware classes
22
25
  # and arguments that are currently applied to the
23
26
  # application.
24
27
  def middleware
25
- settings.stack.inject([]) do |a, s|
26
- a += s[:middleware] if s[:middleware]
27
- a
28
- end
28
+ namespace_stackable(:middleware) || []
29
29
  end
30
30
  end
31
31
  end
@@ -6,11 +6,11 @@ module Grape
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  def use(*names)
9
- named_params = @api.settings[:named_params] || {}
9
+ named_params = Grape::DSL::Configuration.stacked_hash_to_hash(@api.namespace_stackable(:named_params)) || {}
10
10
  options = names.last.is_a?(Hash) ? names.pop : {}
11
11
  names.each do |name|
12
12
  params_block = named_params.fetch(name) do
13
- raise "Params :#{name} not found!"
13
+ fail "Params :#{name} not found!"
14
14
  end
15
15
  instance_exec(options, &params_block)
16
16
  end
@@ -57,6 +57,10 @@ module Grape
57
57
  validates(attrs, at_least_one_of: true)
58
58
  end
59
59
 
60
+ def all_or_none_of(*attrs)
61
+ validates(attrs, all_or_none_of: true)
62
+ end
63
+
60
64
  def group(*attrs, &block)
61
65
  requires(*attrs, &block)
62
66
  end
@@ -5,46 +5,48 @@ module Grape
5
5
  module RequestResponse
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ include Grape::DSL::Configuration
9
+
8
10
  module ClassMethods
9
11
  # Specify the default format for the API's serializers.
10
12
  # May be `:json` or `:txt` (default).
11
13
  def default_format(new_format = nil)
12
- new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
14
+ namespace_inheritable(:default_format, new_format.nil? ? nil : new_format.to_sym)
13
15
  end
14
16
 
15
17
  # Specify the format for the API's serializers.
16
18
  # May be `:json`, `:xml`, `:txt`, etc.
17
19
  def format(new_format = nil)
18
20
  if new_format
19
- set(:format, new_format.to_sym)
21
+ namespace_inheritable(:format, new_format.to_sym)
20
22
  # define the default error formatters
21
- set(:default_error_formatter, Grape::ErrorFormatter::Base.formatter_for(new_format, {}))
23
+ namespace_inheritable(:default_error_formatter, Grape::ErrorFormatter::Base.formatter_for(new_format, {}))
22
24
  # define a single mime type
23
25
  mime_type = content_types[new_format.to_sym]
24
- raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
25
- settings.imbue(:content_types, new_format.to_sym => mime_type)
26
+ fail Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
27
+ namespace_stackable(:content_types, new_format.to_sym => mime_type)
26
28
  else
27
- settings[:format]
29
+ namespace_inheritable(:format)
28
30
  end
29
31
  end
30
32
 
31
33
  # Specify a custom formatter for a content-type.
32
34
  def formatter(content_type, new_formatter)
33
- settings.imbue(:formatters, content_type.to_sym => new_formatter)
35
+ namespace_stackable(:formatters, content_type.to_sym => new_formatter)
34
36
  end
35
37
 
36
38
  # Specify a custom parser for a content-type.
37
39
  def parser(content_type, new_parser)
38
- settings.imbue(:parsers, content_type.to_sym => new_parser)
40
+ namespace_stackable(:parsers, content_type.to_sym => new_parser)
39
41
  end
40
42
 
41
43
  # Specify a default error formatter.
42
44
  def default_error_formatter(new_formatter_name = nil)
43
45
  if new_formatter_name
44
46
  new_formatter = Grape::ErrorFormatter::Base.formatter_for(new_formatter_name, {})
45
- set(:default_error_formatter, new_formatter)
47
+ namespace_inheritable(:default_error_formatter, new_formatter)
46
48
  else
47
- settings[:default_error_formatter]
49
+ namespace_inheritable(:default_error_formatter)
48
50
  end
49
51
  end
50
52
 
@@ -55,23 +57,24 @@ module Grape
55
57
  formatter = options
56
58
  end
57
59
 
58
- settings.imbue(:error_formatters, format.to_sym => formatter)
60
+ namespace_stackable(:error_formatters, format.to_sym => formatter)
59
61
  end
60
62
 
61
63
  # Specify additional content-types, e.g.:
62
64
  # content_type :xls, 'application/vnd.ms-excel'
63
65
  def content_type(key, val)
64
- settings.imbue(:content_types, key.to_sym => val)
66
+ namespace_stackable(:content_types, key.to_sym => val)
65
67
  end
66
68
 
67
69
  # All available content types.
68
70
  def content_types
69
- Grape::ContentTypes.content_types_for(settings[:content_types])
71
+ c_types = Grape::DSL::Configuration.stacked_hash_to_hash(namespace_stackable(:content_types))
72
+ Grape::ContentTypes.content_types_for c_types
70
73
  end
71
74
 
72
75
  # Specify the default status code for errors.
73
76
  def default_error_status(new_status = nil)
74
- new_status ? set(:default_error_status, new_status) : settings[:default_error_status]
77
+ namespace_inheritable(:default_error_status, new_status)
75
78
  end
76
79
 
77
80
  # Allows you to rescue certain exceptions that occur to return
@@ -105,8 +108,8 @@ module Grape
105
108
  handler ||= proc { options[:with] } if options.key?(:with)
106
109
 
107
110
  if args.include?(:all)
108
- set(:rescue_all, true)
109
- imbue :all_rescue_handler, handler
111
+ namespace_inheritable(:rescue_all, true)
112
+ namespace_inheritable :all_rescue_handler, handler
110
113
  else
111
114
  handler_type =
112
115
  case options[:rescue_subclasses]
@@ -116,10 +119,10 @@ module Grape
116
119
  :base_only_rescue_handlers
117
120
  end
118
121
 
119
- imbue handler_type, Hash[args.map { |arg| [arg, handler] }]
122
+ namespace_stackable handler_type, Hash[args.map { |arg| [arg, handler] }]
120
123
  end
121
124
 
122
- imbue(:rescue_options, options)
125
+ namespace_stackable(:rescue_options, options)
123
126
  end
124
127
 
125
128
  # Allows you to specify a default representation entity for a
@@ -143,8 +146,8 @@ module Grape
143
146
  # @param model_class [Class] The model class that will be represented.
144
147
  # @option options [Class] :with The entity class that will represent the model.
145
148
  def represent(model_class, options)
146
- raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with] && options[:with].is_a?(Class)
147
- imbue(:representations, model_class => options[:with])
149
+ fail Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with] && options[:with].is_a?(Class)
150
+ namespace_stackable(:representations, model_class => options[:with])
148
151
  end
149
152
  end
150
153
  end
@@ -4,6 +4,7 @@ module Grape
4
4
  module DSL
5
5
  module Routing
6
6
  extend ActiveSupport::Concern
7
+ include Grape::DSL::Configuration
7
8
 
8
9
  module ClassMethods
9
10
  attr_reader :endpoints, :routes, :route_set
@@ -31,12 +32,12 @@ module Grape
31
32
  options ||= {}
32
33
  options = { using: :path }.merge(options)
33
34
 
34
- raise Grape::Exceptions::MissingVendorOption.new if options[:using] == :header && !options.key?(:vendor)
35
+ fail Grape::Exceptions::MissingVendorOption.new if options[:using] == :header && !options.key?(:vendor)
35
36
 
36
37
  @versions = versions | args
37
38
  nest(block) do
38
- set(:version, args)
39
- set(:version_options, options)
39
+ namespace_inheritable(:version, args)
40
+ namespace_inheritable(:version_options, options)
40
41
  end
41
42
  end
42
43
 
@@ -45,33 +46,44 @@ module Grape
45
46
 
46
47
  # Define a root URL prefix for your entire API.
47
48
  def prefix(prefix = nil)
48
- prefix ? set(:root_prefix, prefix) : settings[:root_prefix]
49
+ namespace_inheritable(:root_prefix, prefix)
49
50
  end
50
51
 
51
52
  # Do not route HEAD requests to GET requests automatically
52
53
  def do_not_route_head!
53
- set(:do_not_route_head, true)
54
+ namespace_inheritable(:do_not_route_head, true)
54
55
  end
55
56
 
56
57
  # Do not automatically route OPTIONS
57
58
  def do_not_route_options!
58
- set(:do_not_route_options, true)
59
+ namespace_inheritable(:do_not_route_options, true)
59
60
  end
60
61
 
61
62
  def mount(mounts)
62
63
  mounts = { mounts => '/' } unless mounts.respond_to?(:each_pair)
63
64
  mounts.each_pair do |app, path|
64
- if app.respond_to?(:inherit_settings, true)
65
- app_settings = settings.clone
66
- mount_path = Rack::Mount::Utils.normalize_path([settings[:mount_path], path].compact.join("/"))
67
- app_settings.set :mount_path, mount_path
68
- app.inherit_settings(app_settings)
65
+ in_setting = inheritable_setting
66
+
67
+ if app.respond_to?(:inheritable_setting, true)
68
+ mount_path = Rack::Mount::Utils.normalize_path(path)
69
+ app.top_level_setting.namespace_stackable[:mount_path] = mount_path
70
+
71
+ app.inherit_settings(inheritable_setting)
72
+
73
+ in_setting = app.top_level_setting
74
+
75
+ # app.regenerate_endpoints(in_setting)
76
+
77
+ app.change!
78
+ change!
69
79
  end
80
+
70
81
  endpoints << Grape::Endpoint.new(
71
- settings.clone,
82
+ in_setting,
72
83
  method: :any,
73
84
  path: path,
74
- app: app
85
+ app: app,
86
+ for: self
75
87
  )
76
88
  end
77
89
  end
@@ -92,53 +104,40 @@ module Grape
92
104
  endpoint_options = {
93
105
  method: methods,
94
106
  path: paths,
95
- route_options: (@namespace_description || {}).deep_merge(@last_description || {}).deep_merge(route_options || {})
107
+ for: self,
108
+ route_options: ({
109
+ params: Grape::DSL::Configuration.stacked_hash_to_hash(namespace_stackable(:params)) || {}
110
+ }).deep_merge(route_setting(:description) || {}).deep_merge(route_options || {})
96
111
  }
97
- endpoints << Grape::Endpoint.new(settings.clone, endpoint_options, &block)
98
112
 
99
- @last_description = nil
100
- reset_validations!
101
- end
102
-
103
- def get(paths = ['/'], options = {}, &block)
104
- route('GET', paths, options, &block)
105
- end
106
-
107
- def post(paths = ['/'], options = {}, &block)
108
- route('POST', paths, options, &block)
109
- end
113
+ endpoints << Grape::Endpoint.new(inheritable_setting, endpoint_options, &block)
110
114
 
111
- def put(paths = ['/'], options = {}, &block)
112
- route('PUT', paths, options, &block)
113
- end
114
-
115
- def head(paths = ['/'], options = {}, &block)
116
- route('HEAD', paths, options, &block)
117
- end
118
-
119
- def delete(paths = ['/'], options = {}, &block)
120
- route('DELETE', paths, options, &block)
121
- end
122
-
123
- def options(paths = ['/'], options = {}, &block)
124
- route('OPTIONS', paths, options, &block)
115
+ route_end
116
+ reset_validations!
125
117
  end
126
118
 
127
- def patch(paths = ['/'], options = {}, &block)
128
- route('PATCH', paths, options, &block)
119
+ %w"get post put head delete options patch".each do |meth|
120
+ define_method meth do |*args, &block|
121
+ options = args.extract_options!
122
+ paths = args.first || ['/']
123
+ route(meth.upcase, paths, options, &block)
124
+ end
129
125
  end
130
126
 
131
127
  def namespace(space = nil, options = {}, &block)
132
128
  if space || block_given?
133
- previous_namespace_description = @namespace_description
134
- @namespace_description = (@namespace_description || {}).deep_merge(@last_description || {})
135
- @last_description = nil
136
- nest(block) do
137
- set(:namespace, Namespace.new(space, options)) if space
129
+ within_namespace do
130
+ previous_namespace_description = @namespace_description
131
+ @namespace_description = (@namespace_description || {}).deep_merge(namespace_setting(:description) || {})
132
+ nest(block) do
133
+ if space
134
+ namespace_stackable(:namespace, Namespace.new(space, options))
135
+ end
136
+ end
137
+ @namespace_description = previous_namespace_description
138
138
  end
139
- @namespace_description = previous_namespace_description
140
139
  else
141
- Namespace.joined_space_path(settings)
140
+ Namespace.joined_space_path(namespace_stackable(:namespace))
142
141
  end
143
142
  end
144
143
 
@@ -152,6 +151,10 @@ module Grape
152
151
  @routes ||= prepare_routes
153
152
  end
154
153
 
154
+ def reset_routes!
155
+ @routes = nil
156
+ end
157
+
155
158
  # Thie method allows you to quickly define a parameter route segment
156
159
  # in your API.
157
160
  #
@@ -0,0 +1,110 @@
1
+ require 'active_support/concern'
2
+
3
+ module Grape
4
+ module DSL
5
+ module Settings
6
+ extend ActiveSupport::Concern
7
+
8
+ attr_accessor :inheritable_setting, :top_level_setting
9
+
10
+ def top_level_setting
11
+ @top_level_setting ||= Grape::Util::InheritableSetting.new
12
+ end
13
+
14
+ def inheritable_setting
15
+ @inheritable_setting ||= Grape::Util::InheritableSetting.new.tap { |new_settings| new_settings.inherit_from top_level_setting }
16
+ end
17
+
18
+ def unset(type, key)
19
+ setting = inheritable_setting.send(type)
20
+ setting.delete key
21
+ end
22
+
23
+ def get_or_set(type, key, value)
24
+ setting = inheritable_setting.send(type)
25
+ if value.nil?
26
+ setting[key]
27
+ else
28
+ setting[key] = value
29
+ end
30
+ end
31
+
32
+ def global_setting(key, value = nil)
33
+ get_or_set :global, key, value
34
+ end
35
+
36
+ def unset_global_setting(key)
37
+ unset :global, key
38
+ end
39
+
40
+ def route_setting(key, value = nil)
41
+ get_or_set :route, key, value
42
+ end
43
+
44
+ def unset_route_setting(key)
45
+ unset :route, key
46
+ end
47
+
48
+ def namespace_setting(key, value = nil)
49
+ get_or_set :namespace, key, value
50
+ end
51
+
52
+ def unset_namespace_setting(key)
53
+ unset :namespace_setting, key
54
+ end
55
+
56
+ def namespace_inheritable(key, value = nil)
57
+ get_or_set :namespace_inheritable, key, value
58
+ end
59
+
60
+ def unset_namespace_inheritable(key)
61
+ unset :namespace_inheritable, key
62
+ end
63
+
64
+ def namespace_inheritable_to_nil(key)
65
+ inheritable_setting.namespace_inheritable[key] = nil
66
+ end
67
+
68
+ def namespace_stackable(key, value = nil)
69
+ get_or_set :namespace_stackable, key, value
70
+ end
71
+
72
+ def unset_namespace_stackable(key)
73
+ unset :namespace_stackable, key
74
+ end
75
+
76
+ def api_class_setting(key, value = nil)
77
+ get_or_set :api_class, key, value
78
+ end
79
+
80
+ def unset_api_class_setting(key)
81
+ unset :api_class_setting, key
82
+ end
83
+
84
+ def namespace_start
85
+ @inheritable_setting = Grape::Util::InheritableSetting.new.tap { |new_settings| new_settings.inherit_from inheritable_setting }
86
+ end
87
+
88
+ def namespace_end
89
+ route_end
90
+ @inheritable_setting = inheritable_setting.parent
91
+ end
92
+
93
+ def route_end
94
+ inheritable_setting.route_end
95
+ reset_validations!
96
+ end
97
+
98
+ def within_namespace(&block)
99
+ namespace_start
100
+
101
+ result = yield if block_given?
102
+
103
+ namespace_end
104
+ reset_validations!
105
+
106
+ result
107
+ end
108
+ end
109
+ end
110
+ end