grape 1.1.0 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|