grape 1.1.0 → 1.2.5
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 +128 -43
- data/LICENSE +1 -1
- data/README.md +394 -47
- data/UPGRADING.md +111 -0
- data/grape.gemspec +3 -1
- data/lib/grape.rb +98 -66
- data/lib/grape/api.rb +136 -175
- data/lib/grape/api/instance.rb +280 -0
- data/lib/grape/config.rb +32 -0
- data/lib/grape/dsl/callbacks.rb +20 -0
- data/lib/grape/dsl/desc.rb +39 -7
- data/lib/grape/dsl/inside_route.rb +12 -6
- data/lib/grape/dsl/middleware.rb +7 -0
- data/lib/grape/dsl/parameters.rb +9 -4
- data/lib/grape/dsl/routing.rb +5 -1
- data/lib/grape/dsl/validations.rb +4 -3
- data/lib/grape/eager_load.rb +18 -0
- data/lib/grape/endpoint.rb +42 -26
- data/lib/grape/error_formatter.rb +1 -1
- data/lib/grape/exceptions/base.rb +9 -1
- data/lib/grape/exceptions/invalid_response.rb +9 -0
- data/lib/grape/exceptions/validation_errors.rb +4 -2
- data/lib/grape/formatter.rb +1 -1
- data/lib/grape/locale/en.yml +2 -0
- data/lib/grape/middleware/auth/base.rb +2 -4
- data/lib/grape/middleware/base.rb +2 -0
- data/lib/grape/middleware/error.rb +9 -4
- data/lib/grape/middleware/helpers.rb +10 -0
- data/lib/grape/middleware/stack.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +4 -4
- data/lib/grape/parser.rb +1 -1
- data/lib/grape/request.rb +1 -1
- data/lib/grape/router/attribute_translator.rb +2 -0
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/util/base_inheritable.rb +34 -0
- data/lib/grape/util/endpoint_configuration.rb +6 -0
- data/lib/grape/util/inheritable_values.rb +5 -25
- data/lib/grape/util/lazy_block.rb +25 -0
- data/lib/grape/util/lazy_value.rb +95 -0
- data/lib/grape/util/reverse_stackable_values.rb +7 -36
- data/lib/grape/util/stackable_values.rb +19 -22
- data/lib/grape/validations/attributes_iterator.rb +5 -3
- data/lib/grape/validations/multiple_attributes_iterator.rb +11 -0
- data/lib/grape/validations/params_scope.rb +20 -14
- data/lib/grape/validations/single_attribute_iterator.rb +13 -0
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -1
- data/lib/grape/validations/types/file.rb +1 -1
- data/lib/grape/validations/validator_factory.rb +6 -11
- data/lib/grape/validations/validators/all_or_none.rb +6 -13
- data/lib/grape/validations/validators/as.rb +2 -3
- data/lib/grape/validations/validators/at_least_one_of.rb +5 -13
- data/lib/grape/validations/validators/base.rb +11 -10
- data/lib/grape/validations/validators/coerce.rb +4 -0
- data/lib/grape/validations/validators/default.rb +1 -1
- data/lib/grape/validations/validators/exactly_one_of.rb +6 -23
- data/lib/grape/validations/validators/multiple_params_base.rb +14 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +6 -18
- data/lib/grape/validations/validators/same_as.rb +23 -0
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api/defines_boolean_in_params_spec.rb +37 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +59 -0
- data/spec/grape/api_remount_spec.rb +466 -0
- data/spec/grape/api_spec.rb +379 -1
- data/spec/grape/config_spec.rb +17 -0
- data/spec/grape/dsl/desc_spec.rb +40 -16
- data/spec/grape/dsl/middleware_spec.rb +8 -0
- data/spec/grape/dsl/routing_spec.rb +10 -0
- data/spec/grape/endpoint_spec.rb +40 -4
- data/spec/grape/exceptions/base_spec.rb +65 -0
- data/spec/grape/exceptions/invalid_response_spec.rb +11 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +6 -4
- data/spec/grape/integration/rack_spec.rb +22 -6
- data/spec/grape/middleware/auth/dsl_spec.rb +3 -3
- data/spec/grape/middleware/base_spec.rb +8 -0
- data/spec/grape/middleware/exception_spec.rb +1 -1
- data/spec/grape/middleware/formatter_spec.rb +15 -5
- data/spec/grape/middleware/versioner/header_spec.rb +6 -0
- data/spec/grape/named_api_spec.rb +19 -0
- data/spec/grape/request_spec.rb +24 -0
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +29 -0
- data/spec/grape/validations/params_scope_spec.rb +184 -8
- data/spec/grape/validations/single_attribute_iterator_spec.rb +33 -0
- data/spec/grape/validations/validators/all_or_none_spec.rb +138 -30
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +173 -29
- data/spec/grape/validations/validators/coerce_spec.rb +10 -2
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +202 -38
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +184 -27
- data/spec/grape/validations/validators/same_as_spec.rb +63 -0
- data/spec/grape/validations_spec.rb +33 -21
- data/spec/spec_helper.rb +4 -1
- metadata +35 -23
- data/Appraisals +0 -32
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile +0 -35
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_edge.gemfile +0 -35
- data/pkg/grape-0.17.0.gem +0 -0
- data/pkg/grape-0.19.0.gem +0 -0
@@ -0,0 +1,280 @@
|
|
1
|
+
require 'grape/router'
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
class API
|
5
|
+
# The API Instance class, is the engine behind Grape::API. Each class that inherits
|
6
|
+
# from this will represent a different API instance
|
7
|
+
class Instance
|
8
|
+
include Grape::DSL::API
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :instance
|
12
|
+
attr_reader :base
|
13
|
+
attr_accessor :configuration
|
14
|
+
|
15
|
+
def given(conditional_option, &block)
|
16
|
+
evaluate_as_instance_with_configuration(block, lazy: true) if conditional_option && block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
def mounted(&block)
|
20
|
+
evaluate_as_instance_with_configuration(block, lazy: true)
|
21
|
+
end
|
22
|
+
|
23
|
+
def base=(grape_api)
|
24
|
+
@base = grape_api
|
25
|
+
grape_api.instances << self
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
(base && base.to_s) || super
|
30
|
+
end
|
31
|
+
|
32
|
+
def base_instance?
|
33
|
+
self == base.base_instance
|
34
|
+
end
|
35
|
+
|
36
|
+
# A class-level lock to ensure the API is not compiled by multiple
|
37
|
+
# threads simultaneously within the same process.
|
38
|
+
LOCK = Mutex.new
|
39
|
+
|
40
|
+
# Clears all defined routes, endpoints, etc., on this API.
|
41
|
+
def reset!
|
42
|
+
reset_endpoints!
|
43
|
+
reset_routes!
|
44
|
+
reset_validations!
|
45
|
+
end
|
46
|
+
|
47
|
+
# Parses the API's definition and compiles it into an instance of
|
48
|
+
# Grape::API.
|
49
|
+
def compile
|
50
|
+
@instance ||= new
|
51
|
+
end
|
52
|
+
|
53
|
+
# Wipe the compiled API so we can recompile after changes were made.
|
54
|
+
def change!
|
55
|
+
@instance = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
# This is the interface point between Rack and Grape; it accepts a request
|
59
|
+
# from Rack and ultimately returns an array of three values: the status,
|
60
|
+
# the headers, and the body. See [the rack specification]
|
61
|
+
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
|
62
|
+
def call(env)
|
63
|
+
compile!
|
64
|
+
call!(env)
|
65
|
+
end
|
66
|
+
|
67
|
+
# A non-synchronized version of ::call.
|
68
|
+
def call!(env)
|
69
|
+
instance.call(env)
|
70
|
+
end
|
71
|
+
|
72
|
+
# (see #cascade?)
|
73
|
+
def cascade(value = nil)
|
74
|
+
if value.nil?
|
75
|
+
inheritable_setting.namespace_inheritable.keys.include?(:cascade) ? !namespace_inheritable(:cascade).nil? : true
|
76
|
+
else
|
77
|
+
namespace_inheritable(:cascade, value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def compile!
|
82
|
+
return if instance
|
83
|
+
LOCK.synchronize { compile unless instance }
|
84
|
+
end
|
85
|
+
|
86
|
+
# see Grape::Router#recognize_path
|
87
|
+
def recognize_path(path)
|
88
|
+
compile!
|
89
|
+
instance.router.recognize_path(path)
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
def prepare_routes
|
95
|
+
endpoints.map(&:routes).flatten
|
96
|
+
end
|
97
|
+
|
98
|
+
# Execute first the provided block, then each of the
|
99
|
+
# block passed in. Allows for simple 'before' setups
|
100
|
+
# of settings stack pushes.
|
101
|
+
def nest(*blocks, &block)
|
102
|
+
blocks.reject!(&:nil?)
|
103
|
+
if blocks.any?
|
104
|
+
evaluate_as_instance_with_configuration(block) if block_given?
|
105
|
+
blocks.each { |b| evaluate_as_instance_with_configuration(b) }
|
106
|
+
reset_validations!
|
107
|
+
else
|
108
|
+
instance_eval(&block)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def evaluate_as_instance_with_configuration(block, lazy: false)
|
113
|
+
lazy_block = Grape::Util::LazyBlock.new do |configuration|
|
114
|
+
value_for_configuration = configuration
|
115
|
+
if value_for_configuration.respond_to?(:lazy?) && value_for_configuration.lazy?
|
116
|
+
self.configuration = value_for_configuration.evaluate
|
117
|
+
end
|
118
|
+
response = instance_eval(&block)
|
119
|
+
self.configuration = value_for_configuration
|
120
|
+
response
|
121
|
+
end
|
122
|
+
if base_instance? && lazy
|
123
|
+
lazy_block
|
124
|
+
else
|
125
|
+
lazy_block.evaluate_from(configuration)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def inherited(subclass)
|
130
|
+
subclass.reset!
|
131
|
+
subclass.logger = logger.clone
|
132
|
+
end
|
133
|
+
|
134
|
+
def inherit_settings(other_settings)
|
135
|
+
top_level_setting.inherit_from other_settings.point_in_time_copy
|
136
|
+
|
137
|
+
# Propagate any inherited params down to our endpoints, and reset any
|
138
|
+
# compiled routes.
|
139
|
+
endpoints.each do |e|
|
140
|
+
e.inherit_settings(top_level_setting.namespace_stackable)
|
141
|
+
e.reset_routes!
|
142
|
+
end
|
143
|
+
|
144
|
+
reset_routes!
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
attr_reader :router
|
149
|
+
|
150
|
+
# Builds the routes from the defined endpoints, effectively compiling
|
151
|
+
# this API into a usable form.
|
152
|
+
def initialize
|
153
|
+
@router = Router.new
|
154
|
+
add_head_not_allowed_methods_and_options_methods
|
155
|
+
self.class.endpoints.each do |endpoint|
|
156
|
+
endpoint.mount_in(@router)
|
157
|
+
end
|
158
|
+
|
159
|
+
@router.compile!
|
160
|
+
@router.freeze
|
161
|
+
end
|
162
|
+
|
163
|
+
# Handle a request. See Rack documentation for what `env` is.
|
164
|
+
def call(env)
|
165
|
+
result = @router.call(env)
|
166
|
+
result[1].delete(Grape::Http::Headers::X_CASCADE) unless cascade?
|
167
|
+
result
|
168
|
+
end
|
169
|
+
|
170
|
+
# Some requests may return a HTTP 404 error if grape cannot find a matching
|
171
|
+
# route. In this case, Grape::Router adds a X-Cascade header to the response
|
172
|
+
# and sets it to 'pass', indicating to grape's parents they should keep
|
173
|
+
# looking for a matching route on other resources.
|
174
|
+
#
|
175
|
+
# In some applications (e.g. mounting grape on rails), one might need to trap
|
176
|
+
# errors from reaching upstream. This is effectivelly done by unsetting
|
177
|
+
# X-Cascade. Default :cascade is true.
|
178
|
+
def cascade?
|
179
|
+
return self.class.namespace_inheritable(:cascade) if self.class.inheritable_setting.namespace_inheritable.keys.include?(:cascade)
|
180
|
+
return self.class.namespace_inheritable(:version_options)[:cascade] if self.class.namespace_inheritable(:version_options) && self.class.namespace_inheritable(:version_options).key?(:cascade)
|
181
|
+
true
|
182
|
+
end
|
183
|
+
|
184
|
+
reset!
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
# For every resource add a 'OPTIONS' route that returns an HTTP 204 response
|
189
|
+
# with a list of HTTP methods that can be called. Also add a route that
|
190
|
+
# will return an HTTP 405 response for any HTTP method that the resource
|
191
|
+
# cannot handle.
|
192
|
+
def add_head_not_allowed_methods_and_options_methods
|
193
|
+
routes_map = {}
|
194
|
+
|
195
|
+
self.class.endpoints.each do |endpoint|
|
196
|
+
routes = endpoint.routes
|
197
|
+
routes.each do |route|
|
198
|
+
# using the :any shorthand produces [nil] for route methods, substitute all manually
|
199
|
+
route_key = route.pattern.to_regexp
|
200
|
+
routes_map[route_key] ||= {}
|
201
|
+
route_settings = routes_map[route_key]
|
202
|
+
route_settings[:pattern] = route.pattern
|
203
|
+
route_settings[:requirements] = route.requirements
|
204
|
+
route_settings[:path] = route.origin
|
205
|
+
route_settings[:methods] ||= []
|
206
|
+
route_settings[:methods] << route.request_method
|
207
|
+
route_settings[:endpoint] = route.app
|
208
|
+
|
209
|
+
# using the :any shorthand produces [nil] for route methods, substitute all manually
|
210
|
+
route_settings[:methods] = %w[GET PUT POST DELETE PATCH HEAD OPTIONS] if route_settings[:methods].include?('*')
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# The paths we collected are prepared (cf. Path#prepare), so they
|
215
|
+
# contain already versioning information when using path versioning.
|
216
|
+
# Disable versioning so adding a route won't prepend versioning
|
217
|
+
# informations again.
|
218
|
+
without_root_prefix do
|
219
|
+
without_versioning do
|
220
|
+
routes_map.each_value do |config|
|
221
|
+
methods = config[:methods]
|
222
|
+
allowed_methods = methods.dup
|
223
|
+
|
224
|
+
unless self.class.namespace_inheritable(:do_not_route_head)
|
225
|
+
allowed_methods |= [Grape::Http::Headers::HEAD] if allowed_methods.include?(Grape::Http::Headers::GET)
|
226
|
+
end
|
227
|
+
|
228
|
+
allow_header = (self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Grape::Http::Headers::OPTIONS] | allowed_methods).join(', ')
|
229
|
+
|
230
|
+
unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Grape::Http::Headers::OPTIONS)
|
231
|
+
config[:endpoint].options[:options_route_enabled] = true
|
232
|
+
end
|
233
|
+
|
234
|
+
attributes = config.merge(allowed_methods: allowed_methods, allow_header: allow_header)
|
235
|
+
generate_not_allowed_method(config[:pattern], attributes)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Generate a route that returns an HTTP 405 response for a user defined
|
242
|
+
# path on methods not specified
|
243
|
+
def generate_not_allowed_method(pattern, allowed_methods: [], **attributes)
|
244
|
+
not_allowed_methods = %w[GET PUT POST DELETE PATCH HEAD] - allowed_methods
|
245
|
+
not_allowed_methods << Grape::Http::Headers::OPTIONS if self.class.namespace_inheritable(:do_not_route_options)
|
246
|
+
|
247
|
+
return if not_allowed_methods.empty?
|
248
|
+
|
249
|
+
@router.associate_routes(pattern, not_allowed_methods: not_allowed_methods, **attributes)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Allows definition of endpoints that ignore the versioning configuration
|
253
|
+
# used by the rest of your API.
|
254
|
+
def without_versioning(&_block)
|
255
|
+
old_version = self.class.namespace_inheritable(:version)
|
256
|
+
old_version_options = self.class.namespace_inheritable(:version_options)
|
257
|
+
|
258
|
+
self.class.namespace_inheritable_to_nil(:version)
|
259
|
+
self.class.namespace_inheritable_to_nil(:version_options)
|
260
|
+
|
261
|
+
yield
|
262
|
+
|
263
|
+
self.class.namespace_inheritable(:version, old_version)
|
264
|
+
self.class.namespace_inheritable(:version_options, old_version_options)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Allows definition of endpoints that ignore the root prefix used by the
|
268
|
+
# rest of your API.
|
269
|
+
def without_root_prefix(&_block)
|
270
|
+
old_prefix = self.class.namespace_inheritable(:root_prefix)
|
271
|
+
|
272
|
+
self.class.namespace_inheritable_to_nil(:root_prefix)
|
273
|
+
|
274
|
+
yield
|
275
|
+
|
276
|
+
self.class.namespace_inheritable(:root_prefix, old_prefix)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
data/lib/grape/config.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Grape
|
2
|
+
module Config
|
3
|
+
class Configuration
|
4
|
+
ATTRIBUTES = %i[
|
5
|
+
param_builder
|
6
|
+
].freeze
|
7
|
+
|
8
|
+
attr_accessor(*ATTRIBUTES)
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
reset
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
self.param_builder = Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.extended(base)
|
20
|
+
def base.configure
|
21
|
+
block_given? ? yield(config) : config
|
22
|
+
end
|
23
|
+
|
24
|
+
def base.config
|
25
|
+
@configuration ||= Grape::Config::Configuration.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Grape.extend Grape::Config
|
32
|
+
Grape.config.reset
|
data/lib/grape/dsl/callbacks.rb
CHANGED
@@ -43,6 +43,26 @@ module Grape
|
|
43
43
|
def after(&block)
|
44
44
|
namespace_stackable(:afters, block)
|
45
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 close 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)
|
65
|
+
end
|
46
66
|
end
|
47
67
|
end
|
48
68
|
end
|
data/lib/grape/dsl/desc.rb
CHANGED
@@ -9,6 +9,7 @@ module Grape
|
|
9
9
|
# @param options [Hash] other properties you can set to describe the
|
10
10
|
# endpoint or namespace. Optional.
|
11
11
|
# @option options :detail [String] additional detail about this endpoint
|
12
|
+
# @option options :summary [String] summary for this endpoint
|
12
13
|
# @option options :params [Hash] param types and info. normally, you set
|
13
14
|
# these via the `params` dsl method.
|
14
15
|
# @option options :entity [Grape::Entity] the entity returned upon a
|
@@ -16,7 +17,16 @@ module Grape
|
|
16
17
|
# @option options :http_codes [Array[Array]] possible HTTP codes this
|
17
18
|
# endpoint may return, with their meanings, in a 2d array
|
18
19
|
# @option options :named [String] a specific name to help find this route
|
20
|
+
# @option options :body_name [String] override the autogenerated body name param
|
19
21
|
# @option options :headers [Hash] HTTP headers this method can accept
|
22
|
+
# @option options :hidden [Boolean] hide the endpoint or not
|
23
|
+
# @option options :deprecated [Boolean] deprecate the endpoint or not
|
24
|
+
# @option options :is_array [Boolean] response entity is array or not
|
25
|
+
# @option options :nickname [String] nickname of the endpoint
|
26
|
+
# @option options :produces [Array[String]] a list of MIME types the endpoint produce
|
27
|
+
# @option options :consumes [Array[String]] a list of MIME types the endpoint consume
|
28
|
+
# @option options :security [Array[Hash]] a list of security schemes
|
29
|
+
# @option options :tags [Array[String]] a list of tags
|
20
30
|
# @yield a block yielding an instance context with methods mapping to
|
21
31
|
# each of the above, except that :entity is also aliased as #success
|
22
32
|
# and :http_codes is aliased as #failure.
|
@@ -39,7 +49,17 @@ module Grape
|
|
39
49
|
#
|
40
50
|
def desc(description, options = {}, &config_block)
|
41
51
|
if block_given?
|
42
|
-
|
52
|
+
endpoint_configuration = if defined?(configuration)
|
53
|
+
# When the instance is mounted - the configuration is executed on mount time
|
54
|
+
if configuration.respond_to?(:evaluate)
|
55
|
+
configuration.evaluate
|
56
|
+
# Within `given` or `mounted blocks` the configuration is already evaluated
|
57
|
+
elsif configuration.is_a?(Hash)
|
58
|
+
configuration
|
59
|
+
end
|
60
|
+
end
|
61
|
+
endpoint_configuration ||= {}
|
62
|
+
config_class = desc_container(endpoint_configuration)
|
43
63
|
|
44
64
|
config_class.configure do
|
45
65
|
description description
|
@@ -59,13 +79,12 @@ module Grape
|
|
59
79
|
end
|
60
80
|
|
61
81
|
def description_field(field, value = nil)
|
82
|
+
description = route_setting(:description)
|
62
83
|
if value
|
63
|
-
description = route_setting(:description)
|
64
84
|
description ||= route_setting(:description, {})
|
65
85
|
description[field] = value
|
66
|
-
|
67
|
-
description
|
68
|
-
description[field] if description
|
86
|
+
elsif description
|
87
|
+
description[field]
|
69
88
|
end
|
70
89
|
end
|
71
90
|
|
@@ -75,17 +94,30 @@ module Grape
|
|
75
94
|
end
|
76
95
|
|
77
96
|
# Returns an object which configures itself via an instance-context DSL.
|
78
|
-
def desc_container
|
97
|
+
def desc_container(endpoint_configuration)
|
79
98
|
Module.new do
|
80
99
|
include Grape::Util::StrictHashConfiguration.module(
|
100
|
+
:summary,
|
81
101
|
:description,
|
82
102
|
:detail,
|
83
103
|
:params,
|
84
104
|
:entity,
|
85
105
|
:http_codes,
|
86
106
|
:named,
|
87
|
-
:
|
107
|
+
:body_name,
|
108
|
+
:headers,
|
109
|
+
:hidden,
|
110
|
+
:deprecated,
|
111
|
+
:is_array,
|
112
|
+
:nickname,
|
113
|
+
:produces,
|
114
|
+
:consumes,
|
115
|
+
:security,
|
116
|
+
:tags
|
88
117
|
)
|
118
|
+
config_context.define_singleton_method(:configuration) do
|
119
|
+
endpoint_configuration
|
120
|
+
end
|
89
121
|
|
90
122
|
def config_context.success(*args)
|
91
123
|
entity(*args)
|
@@ -61,13 +61,13 @@ module Grape
|
|
61
61
|
else
|
62
62
|
# If it is not a Hash then it does not have children.
|
63
63
|
# Find its value or set it to nil.
|
64
|
-
|
65
|
-
|
64
|
+
has_renaming = route_setting(:renamed_params) && route_setting(:renamed_params).find { |current| current[declared_param] }
|
65
|
+
param_renaming = has_renaming[declared_param] if has_renaming
|
66
66
|
|
67
|
-
next unless options[:include_missing] || passed_params.key?(declared_param) || (
|
67
|
+
next unless options[:include_missing] || passed_params.key?(declared_param) || (param_renaming && passed_params.key?(param_renaming))
|
68
68
|
|
69
|
-
if
|
70
|
-
memo[optioned_param_key(
|
69
|
+
if param_renaming
|
70
|
+
memo[optioned_param_key(param_renaming, options)] = passed_params[param_renaming]
|
71
71
|
else
|
72
72
|
memo[optioned_param_key(declared_param, options)] = passed_params[declared_param]
|
73
73
|
end
|
@@ -129,13 +129,19 @@ module Grape
|
|
129
129
|
env[Grape::Env::API_VERSION]
|
130
130
|
end
|
131
131
|
|
132
|
+
def configuration
|
133
|
+
options[:for].configuration.evaluate
|
134
|
+
end
|
135
|
+
|
132
136
|
# End the request and display an error to the
|
133
137
|
# end user with the specified message.
|
134
138
|
#
|
135
139
|
# @param message [String] The message to display.
|
136
140
|
# @param status [Integer] the HTTP Status Code. Defaults to default_error_status, 500 if not set.
|
137
|
-
|
141
|
+
# @param additional_headers [Hash] Addtional headers for the response.
|
142
|
+
def error!(message, status = nil, additional_headers = nil)
|
138
143
|
self.status(status || namespace_inheritable(:default_error_status))
|
144
|
+
headers = additional_headers.present? ? header.merge(additional_headers) : header
|
139
145
|
throw :error, message: message, status: self.status, headers: headers
|
140
146
|
end
|
141
147
|
|