grape 2.3.0 → 3.0.0
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 +69 -0
- data/CONTRIBUTING.md +2 -10
- data/README.md +106 -43
- data/UPGRADING.md +90 -1
- data/grape.gemspec +4 -4
- data/lib/grape/api/instance.rb +51 -73
- data/lib/grape/api.rb +56 -89
- data/lib/grape/cookies.rb +31 -25
- data/lib/grape/dry_types.rb +48 -4
- data/lib/grape/dsl/callbacks.rb +8 -58
- data/lib/grape/dsl/desc.rb +8 -67
- data/lib/grape/dsl/headers.rb +1 -1
- data/lib/grape/dsl/helpers.rb +60 -65
- data/lib/grape/dsl/inside_route.rb +26 -61
- data/lib/grape/dsl/logger.rb +3 -6
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +10 -19
- data/lib/grape/dsl/request_response.rb +136 -139
- data/lib/grape/dsl/routing.rb +230 -194
- data/lib/grape/dsl/settings.rb +22 -134
- data/lib/grape/dsl/validations.rb +37 -45
- data/lib/grape/endpoint.rb +91 -126
- data/lib/grape/error_formatter/base.rb +2 -0
- data/lib/grape/exceptions/base.rb +1 -1
- data/lib/grape/exceptions/conflicting_types.rb +11 -0
- data/lib/grape/exceptions/invalid_parameters.rb +11 -0
- data/lib/grape/exceptions/missing_group_type.rb +0 -2
- data/lib/grape/exceptions/too_deep_parameters.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
- data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +2 -5
- data/lib/grape/extensions/hash.rb +2 -1
- data/lib/grape/extensions/hashie/mash.rb +3 -5
- data/lib/grape/locale/en.yml +44 -44
- data/lib/grape/middleware/auth/base.rb +11 -32
- data/lib/grape/middleware/auth/dsl.rb +22 -29
- data/lib/grape/middleware/base.rb +30 -11
- data/lib/grape/middleware/error.rb +14 -32
- data/lib/grape/middleware/formatter.rb +40 -72
- data/lib/grape/middleware/stack.rb +28 -38
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -4
- data/lib/grape/middleware/versioner/base.rb +30 -56
- data/lib/grape/middleware/versioner/header.rb +2 -2
- data/lib/grape/middleware/versioner/param.rb +2 -3
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/namespace.rb +11 -0
- data/lib/grape/params_builder/base.rb +20 -0
- data/lib/grape/params_builder/hash.rb +11 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
- data/lib/grape/params_builder/hashie_mash.rb +11 -0
- data/lib/grape/params_builder.rb +32 -0
- data/lib/grape/request.rb +161 -22
- data/lib/grape/router/route.rb +1 -1
- data/lib/grape/router.rb +27 -8
- data/lib/grape/util/api_description.rb +56 -0
- data/lib/grape/util/base_inheritable.rb +5 -2
- data/lib/grape/util/inheritable_setting.rb +7 -0
- data/lib/grape/util/media_type.rb +1 -1
- data/lib/grape/util/registry.rb +1 -1
- data/lib/grape/validations/contract_scope.rb +2 -2
- data/lib/grape/validations/params_documentation.rb +50 -0
- data/lib/grape/validations/params_scope.rb +46 -56
- data/lib/grape/validations/types/array_coercer.rb +2 -3
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -11
- data/lib/grape/validations/types/primitive_coercer.rb +1 -28
- data/lib/grape/validations/types.rb +10 -25
- data/lib/grape/validations/validators/base.rb +2 -9
- data/lib/grape/validations/validators/except_values_validator.rb +1 -1
- data/lib/grape/validations/validators/presence_validator.rb +1 -1
- data/lib/grape/validations/validators/regexp_validator.rb +1 -1
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +18 -9
- metadata +35 -20
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -19
- data/lib/grape/dsl/configuration.rb +0 -15
- data/lib/grape/error_formatter/jsonapi.rb +0 -7
- data/lib/grape/http/headers.rb +0 -56
- data/lib/grape/middleware/helpers.rb +0 -12
- data/lib/grape/parser/jsonapi.rb +0 -7
- data/lib/grape/types/invalid_value.rb +0 -8
- data/lib/grape/util/lazy/object.rb +0 -45
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/validations/attributes_doc.rb +0 -60
data/lib/grape/dsl/desc.rb
CHANGED
|
@@ -3,28 +3,7 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Desc
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ROUTE_ATTRIBUTES = %i[
|
|
9
|
-
body_name
|
|
10
|
-
consumes
|
|
11
|
-
default
|
|
12
|
-
deprecated
|
|
13
|
-
description
|
|
14
|
-
detail
|
|
15
|
-
entity
|
|
16
|
-
headers
|
|
17
|
-
hidden
|
|
18
|
-
http_codes
|
|
19
|
-
is_array
|
|
20
|
-
named
|
|
21
|
-
nickname
|
|
22
|
-
params
|
|
23
|
-
produces
|
|
24
|
-
security
|
|
25
|
-
summary
|
|
26
|
-
tags
|
|
27
|
-
].freeze
|
|
6
|
+
extend Grape::DSL::Settings
|
|
28
7
|
|
|
29
8
|
# Add a description to the next namespace or function.
|
|
30
9
|
# @param description [String] descriptive string for this endpoint
|
|
@@ -70,54 +49,16 @@ module Grape
|
|
|
70
49
|
# # ...
|
|
71
50
|
# end
|
|
72
51
|
#
|
|
73
|
-
def desc(description, options =
|
|
74
|
-
|
|
52
|
+
def desc(description, options = {}, &config_block)
|
|
53
|
+
settings =
|
|
75
54
|
if config_block
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
description(description)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
config_class.configure(&config_block)
|
|
82
|
-
config_class.settings
|
|
83
|
-
end
|
|
55
|
+
endpoint_config = defined?(configuration) ? configuration : nil
|
|
56
|
+
Grape::Util::ApiDescription.new(description, endpoint_config, &config_block).settings
|
|
84
57
|
else
|
|
85
|
-
options
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
namespace_setting :description, opts
|
|
89
|
-
route_setting :description, opts
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Returns an object which configures itself via an instance-context DSL.
|
|
93
|
-
def desc_container(endpoint_configuration)
|
|
94
|
-
Module.new do
|
|
95
|
-
include Grape::Util::StrictHashConfiguration.module(*ROUTE_ATTRIBUTES)
|
|
96
|
-
config_context.define_singleton_method(:configuration) do
|
|
97
|
-
endpoint_configuration
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def config_context.success(*args)
|
|
101
|
-
entity(*args)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def config_context.failure(*args)
|
|
105
|
-
http_codes(*args)
|
|
58
|
+
options.merge(description: description)
|
|
106
59
|
end
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
def endpoint_configuration
|
|
113
|
-
return {} unless defined?(configuration)
|
|
114
|
-
|
|
115
|
-
if configuration.respond_to?(:evaluate)
|
|
116
|
-
configuration.evaluate
|
|
117
|
-
# Within `given` or `mounted blocks` the configuration is already evaluated
|
|
118
|
-
elsif configuration.is_a?(Hash)
|
|
119
|
-
configuration
|
|
120
|
-
end
|
|
60
|
+
inheritable_setting.namespace[:description] = settings
|
|
61
|
+
inheritable_setting.route[:description] = settings
|
|
121
62
|
end
|
|
122
63
|
end
|
|
123
64
|
end
|
data/lib/grape/dsl/headers.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Grape
|
|
|
10
10
|
# 4. Delete a specifc header key-value pair
|
|
11
11
|
def header(key = nil, val = nil)
|
|
12
12
|
if key
|
|
13
|
-
val ? header[key
|
|
13
|
+
val ? header[key] = val : header.delete(key)
|
|
14
14
|
else
|
|
15
15
|
@header ||= Grape::Util::Header.new
|
|
16
16
|
end
|
data/lib/grape/dsl/helpers.rb
CHANGED
|
@@ -3,81 +3,76 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Helpers
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
include_new_modules(new_modules)
|
|
37
|
-
include_block(block)
|
|
38
|
-
include_all_in_scope if !block && new_modules.empty?
|
|
39
|
-
end
|
|
6
|
+
# Add helper methods that will be accessible from any
|
|
7
|
+
# endpoint within this namespace (and child namespaces).
|
|
8
|
+
#
|
|
9
|
+
# When called without a block, all known helpers within this scope
|
|
10
|
+
# are included.
|
|
11
|
+
#
|
|
12
|
+
# @param [Array] new_modules optional array of modules to include
|
|
13
|
+
# @param [Block] block optional block of methods to include
|
|
14
|
+
#
|
|
15
|
+
# @example Define some helpers.
|
|
16
|
+
#
|
|
17
|
+
# class ExampleAPI < Grape::API
|
|
18
|
+
# helpers do
|
|
19
|
+
# def current_user
|
|
20
|
+
# User.find_by_id(params[:token])
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# @example Include many modules
|
|
26
|
+
#
|
|
27
|
+
# class ExampleAPI < Grape::API
|
|
28
|
+
# helpers Authentication, Mailer, OtherModule
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
def helpers(*new_modules, &block)
|
|
32
|
+
include_new_modules(new_modules)
|
|
33
|
+
include_block(block)
|
|
34
|
+
include_all_in_scope if !block && new_modules.empty?
|
|
35
|
+
end
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
private
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
def include_new_modules(modules)
|
|
40
|
+
return if modules.empty?
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
modules.each { |mod| make_inclusion(mod) }
|
|
43
|
+
end
|
|
48
44
|
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
def include_block(block)
|
|
46
|
+
return unless block
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
end
|
|
48
|
+
Module.new.tap do |mod|
|
|
49
|
+
make_inclusion(mod) { mod.class_eval(&block) }
|
|
55
50
|
end
|
|
51
|
+
end
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
def make_inclusion(mod, &block)
|
|
54
|
+
define_boolean_in_mod(mod)
|
|
55
|
+
inject_api_helpers_to_mod(mod, &block)
|
|
56
|
+
inheritable_setting.namespace_stackable[:helpers] = mod
|
|
57
|
+
end
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
end
|
|
59
|
+
def include_all_in_scope
|
|
60
|
+
Module.new.tap do |mod|
|
|
61
|
+
namespace_stackable(:helpers).each { |mod_to_include| mod.include mod_to_include }
|
|
62
|
+
change!
|
|
68
63
|
end
|
|
64
|
+
end
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
def define_boolean_in_mod(mod)
|
|
67
|
+
return if defined? mod::Boolean
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
mod.const_set(:Boolean, Grape::API::Boolean)
|
|
70
|
+
end
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
end
|
|
72
|
+
def inject_api_helpers_to_mod(mod, &block)
|
|
73
|
+
mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
|
|
74
|
+
yield if block
|
|
75
|
+
mod.api_changed(self)
|
|
81
76
|
end
|
|
82
77
|
|
|
83
78
|
# This module extends user defined helpers
|
|
@@ -98,9 +93,9 @@ module Grape
|
|
|
98
93
|
protected
|
|
99
94
|
|
|
100
95
|
def process_named_params
|
|
101
|
-
return
|
|
96
|
+
return if @named_params.blank?
|
|
102
97
|
|
|
103
|
-
api.namespace_stackable
|
|
98
|
+
api.inheritable_setting.namespace_stackable[:named_params] = @named_params
|
|
104
99
|
end
|
|
105
100
|
end
|
|
106
101
|
end
|
|
@@ -3,10 +3,6 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module InsideRoute
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
include Grape::DSL::Settings
|
|
8
|
-
include Grape::DSL::Headers
|
|
9
|
-
|
|
10
6
|
# Denotes a situation where a DSL method has been invoked in a
|
|
11
7
|
# filter which it should not yet be available in
|
|
12
8
|
class MethodNotYetAvailable < StandardError; end
|
|
@@ -35,7 +31,7 @@ module Grape
|
|
|
35
31
|
declared_hash(passed_params, options, declared_params, params_nested_path)
|
|
36
32
|
end
|
|
37
33
|
|
|
38
|
-
if (key_maps = namespace_stackable
|
|
34
|
+
if (key_maps = inheritable_setting.namespace_stackable[:contract_key_map])
|
|
39
35
|
key_maps.each { |key_map| key_map.write(passed_params, res) }
|
|
40
36
|
end
|
|
41
37
|
|
|
@@ -59,7 +55,7 @@ module Grape
|
|
|
59
55
|
end
|
|
60
56
|
|
|
61
57
|
def declared_hash_attr(passed_params, options, declared_param, params_nested_path, memo)
|
|
62
|
-
renamed_params =
|
|
58
|
+
renamed_params = inheritable_setting.route[:renamed_params] || {}
|
|
63
59
|
if declared_param.is_a?(Hash)
|
|
64
60
|
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
|
65
61
|
params_nested_path_dup = params_nested_path.dup
|
|
@@ -79,7 +75,7 @@ module Grape
|
|
|
79
75
|
else
|
|
80
76
|
# If it is not a Hash then it does not have children.
|
|
81
77
|
# Find its value or set it to nil.
|
|
82
|
-
return unless options[:include_missing] || passed_params.key
|
|
78
|
+
return unless options[:include_missing] || passed_params.try(:key?, declared_param)
|
|
83
79
|
|
|
84
80
|
rename_path = params_nested_path + [declared_param.to_s]
|
|
85
81
|
renamed_param_name = renamed_params[rename_path]
|
|
@@ -107,7 +103,7 @@ module Grape
|
|
|
107
103
|
|
|
108
104
|
if type == 'Hash' && !has_children
|
|
109
105
|
{}
|
|
110
|
-
elsif type == 'Array' || (type&.start_with?('[') && type
|
|
106
|
+
elsif type == 'Array' || (type&.start_with?('[') && type.exclude?(','))
|
|
111
107
|
[]
|
|
112
108
|
elsif type == 'Set' || type&.start_with?('#<Set')
|
|
113
109
|
Set.new
|
|
@@ -123,10 +119,10 @@ module Grape
|
|
|
123
119
|
def optioned_declared_params(include_parent_namespaces)
|
|
124
120
|
declared_params = if include_parent_namespaces
|
|
125
121
|
# Declared params including parent namespaces
|
|
126
|
-
|
|
122
|
+
inheritable_setting.route[:declared_params]
|
|
127
123
|
else
|
|
128
124
|
# Declared params at current namespace
|
|
129
|
-
namespace_stackable
|
|
125
|
+
inheritable_setting.namespace_stackable[:declared_params].last || []
|
|
130
126
|
end
|
|
131
127
|
|
|
132
128
|
raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
|
|
@@ -168,7 +164,7 @@ module Grape
|
|
|
168
164
|
# @param backtrace [Array<String>] The backtrace of the exception that caused the error.
|
|
169
165
|
# @param original_exception [Exception] The original exception that caused the error.
|
|
170
166
|
def error!(message, status = nil, additional_headers = nil, backtrace = nil, original_exception = nil)
|
|
171
|
-
status = self.status(status || namespace_inheritable
|
|
167
|
+
status = self.status(status || inheritable_setting.namespace_inheritable[:default_error_status])
|
|
172
168
|
headers = additional_headers.present? ? header.merge(additional_headers) : header
|
|
173
169
|
throw :error,
|
|
174
170
|
message: message,
|
|
@@ -178,24 +174,6 @@ module Grape
|
|
|
178
174
|
original_exception: original_exception
|
|
179
175
|
end
|
|
180
176
|
|
|
181
|
-
# Creates a Rack response based on the provided message, status, and headers.
|
|
182
|
-
# The content type in the headers is set to the default content type unless provided.
|
|
183
|
-
# The message is HTML-escaped if the content type is 'text/html'.
|
|
184
|
-
#
|
|
185
|
-
# @param message [String] The content of the response.
|
|
186
|
-
# @param status [Integer] The HTTP status code.
|
|
187
|
-
# @params headers [Hash] (optional) Headers for the response
|
|
188
|
-
# (default: {Rack::CONTENT_TYPE => content_type}).
|
|
189
|
-
#
|
|
190
|
-
# Returns:
|
|
191
|
-
# A Rack::Response object containing the specified message, status, and headers.
|
|
192
|
-
#
|
|
193
|
-
def rack_response(message, status = 200, headers = { Rack::CONTENT_TYPE => content_type })
|
|
194
|
-
Grape.deprecator.warn('The rack_response method has been deprecated, use error! instead.')
|
|
195
|
-
message = Rack::Utils.escape_html(message) if headers[Rack::CONTENT_TYPE] == 'text/html'
|
|
196
|
-
Rack::Response.new(Array.wrap(message), Rack::Utils.status_code(status), headers)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
177
|
# Redirect to a new url.
|
|
200
178
|
#
|
|
201
179
|
# @param url [String] The url to be redirect.
|
|
@@ -213,7 +191,7 @@ module Grape
|
|
|
213
191
|
status 302
|
|
214
192
|
body_message ||= "This resource has been moved temporarily to #{url}."
|
|
215
193
|
end
|
|
216
|
-
header
|
|
194
|
+
header 'Location', url
|
|
217
195
|
content_type 'text/plain'
|
|
218
196
|
body body_message
|
|
219
197
|
end
|
|
@@ -257,18 +235,6 @@ module Grape
|
|
|
257
235
|
end
|
|
258
236
|
end
|
|
259
237
|
|
|
260
|
-
# Set or get a cookie
|
|
261
|
-
#
|
|
262
|
-
# @example
|
|
263
|
-
# cookies[:mycookie] = 'mycookie val'
|
|
264
|
-
# cookies['mycookie-string'] = 'mycookie string val'
|
|
265
|
-
# cookies[:more] = { value: '123', expires: Time.at(0) }
|
|
266
|
-
# cookies.delete :more
|
|
267
|
-
#
|
|
268
|
-
def cookies
|
|
269
|
-
@cookies ||= Cookies.new
|
|
270
|
-
end
|
|
271
|
-
|
|
272
238
|
# Allows you to define the response body as something other than the
|
|
273
239
|
# return value.
|
|
274
240
|
#
|
|
@@ -342,7 +308,7 @@ module Grape
|
|
|
342
308
|
return if value.nil? && @stream.nil?
|
|
343
309
|
|
|
344
310
|
header Rack::CONTENT_LENGTH, nil
|
|
345
|
-
header
|
|
311
|
+
header 'Transfer-Encoding', nil
|
|
346
312
|
header Rack::CACHE_CONTROL, 'no-cache' # Skips ETag generation (reading the response up front)
|
|
347
313
|
if value.is_a?(String)
|
|
348
314
|
file_body = Grape::ServeStream::FileBody.new(value)
|
|
@@ -371,8 +337,7 @@ module Grape
|
|
|
371
337
|
# with: API::Entities::User,
|
|
372
338
|
# admin: current_user.admin?
|
|
373
339
|
# end
|
|
374
|
-
def present(*args)
|
|
375
|
-
options = args.count > 1 ? args.extract_options! : {}
|
|
340
|
+
def present(*args, **options)
|
|
376
341
|
key, object = if args.count == 2 && args.first.is_a?(Symbol)
|
|
377
342
|
args
|
|
378
343
|
else
|
|
@@ -423,22 +388,22 @@ module Grape
|
|
|
423
388
|
# @return [Class] the located Entity class, or nil if none is found
|
|
424
389
|
def entity_class_for_obj(object, options)
|
|
425
390
|
entity_class = options.delete(:with)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
entity_class ||= object_class.const_get(:Entity) if object_class.const_defined?(:Entity) && object_class.const_get(:Entity).respond_to?(:represent)
|
|
391
|
+
return entity_class if entity_class
|
|
392
|
+
|
|
393
|
+
# entity class not explicitly defined, auto-detect from relation#klass or first object in the collection
|
|
394
|
+
object_class = if object.respond_to?(:klass)
|
|
395
|
+
object.klass
|
|
396
|
+
else
|
|
397
|
+
object.respond_to?(:first) ? object.first.class : object.class
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
representations = inheritable_setting.namespace_stackable_with_hash(:representations)
|
|
401
|
+
if representations
|
|
402
|
+
potential = object_class.ancestors.detect { |potential| representations.key?(potential) }
|
|
403
|
+
entity_class = representations[potential] if potential
|
|
440
404
|
end
|
|
441
405
|
|
|
406
|
+
entity_class = object_class.const_get(:Entity) if !entity_class && object_class.const_defined?(:Entity) && object_class.const_get(:Entity).respond_to?(:represent)
|
|
442
407
|
entity_class
|
|
443
408
|
end
|
|
444
409
|
|
|
@@ -447,11 +412,11 @@ module Grape
|
|
|
447
412
|
def entity_representation_for(entity_class, object, options)
|
|
448
413
|
embeds = { env: env }
|
|
449
414
|
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
|
450
|
-
entity_class.represent(object, **embeds
|
|
415
|
+
entity_class.represent(object, **embeds, **options)
|
|
451
416
|
end
|
|
452
417
|
|
|
453
418
|
def http_version
|
|
454
|
-
env.fetch(
|
|
419
|
+
env.fetch('HTTP_VERSION') { env[Rack::SERVER_PROTOCOL] }
|
|
455
420
|
end
|
|
456
421
|
|
|
457
422
|
def api_format(format)
|
data/lib/grape/dsl/logger.rb
CHANGED
|
@@ -3,18 +3,15 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Logger
|
|
6
|
-
include Grape::DSL::Settings
|
|
7
|
-
|
|
8
|
-
attr_writer :logger
|
|
9
|
-
|
|
10
6
|
# Set or retrive the configured logger. If none was configured, this
|
|
11
7
|
# method will create a new one, logging to stdout.
|
|
12
8
|
# @param logger [Object] the new logger to use
|
|
13
9
|
def logger(logger = nil)
|
|
10
|
+
global_settings = inheritable_setting.global
|
|
14
11
|
if logger
|
|
15
|
-
|
|
12
|
+
global_settings[:logger] = logger
|
|
16
13
|
else
|
|
17
|
-
|
|
14
|
+
global_settings[:logger] || global_settings[:logger] = ::Logger.new($stdout)
|
|
18
15
|
end
|
|
19
16
|
end
|
|
20
17
|
end
|
data/lib/grape/dsl/middleware.rb
CHANGED
|
@@ -3,51 +3,33 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Middleware
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
arr = [:use, middleware_class, *args]
|
|
19
|
-
arr << block if block
|
|
20
|
-
|
|
21
|
-
namespace_stackable(:middleware, arr)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def insert(*args, &block)
|
|
25
|
-
arr = [:insert, *args]
|
|
26
|
-
arr << block if block
|
|
27
|
-
|
|
28
|
-
namespace_stackable(:middleware, arr)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def insert_before(*args, &block)
|
|
32
|
-
arr = [:insert_before, *args]
|
|
33
|
-
arr << block if block
|
|
34
|
-
|
|
35
|
-
namespace_stackable(:middleware, arr)
|
|
36
|
-
end
|
|
6
|
+
# Apply a custom middleware to the API. Applies
|
|
7
|
+
# to the current namespace and any children, but
|
|
8
|
+
# not parents.
|
|
9
|
+
#
|
|
10
|
+
# @param middleware_class [Class] The class of the middleware you'd like
|
|
11
|
+
# to inject.
|
|
12
|
+
def use(middleware_class, *args, &block)
|
|
13
|
+
arr = [:use, middleware_class, *args]
|
|
14
|
+
arr << block if block
|
|
15
|
+
|
|
16
|
+
inheritable_setting.namespace_stackable[:middleware] = arr
|
|
17
|
+
end
|
|
37
18
|
|
|
38
|
-
|
|
39
|
-
|
|
19
|
+
%i[insert insert_before insert_after].each do |method_name|
|
|
20
|
+
define_method method_name do |*args, &block|
|
|
21
|
+
arr = [method_name, *args]
|
|
40
22
|
arr << block if block
|
|
41
23
|
|
|
42
|
-
namespace_stackable
|
|
24
|
+
inheritable_setting.namespace_stackable[:middleware] = arr
|
|
43
25
|
end
|
|
26
|
+
end
|
|
44
27
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end
|
|
28
|
+
# Retrieve an array of the middleware classes
|
|
29
|
+
# and arguments that are currently applied to the
|
|
30
|
+
# application.
|
|
31
|
+
def middleware
|
|
32
|
+
inheritable_setting.namespace_stackable[:middleware] || []
|
|
51
33
|
end
|
|
52
34
|
end
|
|
53
35
|
end
|
data/lib/grape/dsl/parameters.rb
CHANGED
|
@@ -6,8 +6,6 @@ module Grape
|
|
|
6
6
|
# and describe the parameters accepted by an endpoint, or all endpoints
|
|
7
7
|
# within a namespace.
|
|
8
8
|
module Parameters
|
|
9
|
-
extend ActiveSupport::Concern
|
|
10
|
-
|
|
11
9
|
# Set the module used to build the request.params.
|
|
12
10
|
#
|
|
13
11
|
# @param build_with the ParamBuilder module to use when building request.params
|
|
@@ -23,15 +21,15 @@ module Grape
|
|
|
23
21
|
# class API < Grape::API
|
|
24
22
|
# desc "Get collection"
|
|
25
23
|
# params do
|
|
26
|
-
# build_with
|
|
24
|
+
# build_with :hashie_mash
|
|
27
25
|
# requires :user_id, type: Integer
|
|
28
26
|
# end
|
|
29
27
|
# get do
|
|
30
28
|
# params['user_id']
|
|
31
29
|
# end
|
|
32
30
|
# end
|
|
33
|
-
def build_with(build_with
|
|
34
|
-
@api.namespace_inheritable
|
|
31
|
+
def build_with(build_with)
|
|
32
|
+
@api.inheritable_setting.namespace_inheritable[:build_params_with] = build_with
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
# Include reusable params rules among current.
|
|
@@ -55,9 +53,8 @@ module Grape
|
|
|
55
53
|
# Collection.page(params[:page]).per(params[:per_page])
|
|
56
54
|
# end
|
|
57
55
|
# end
|
|
58
|
-
def use(*names)
|
|
59
|
-
named_params = @api.namespace_stackable_with_hash(:named_params) || {}
|
|
60
|
-
options = names.extract_options!
|
|
56
|
+
def use(*names, **options)
|
|
57
|
+
named_params = @api.inheritable_setting.namespace_stackable_with_hash(:named_params) || {}
|
|
61
58
|
names.each do |name|
|
|
62
59
|
params_block = named_params.fetch(name) do
|
|
63
60
|
raise "Params :#{name} not found!"
|
|
@@ -125,10 +122,7 @@ module Grape
|
|
|
125
122
|
# requires :name, type: String
|
|
126
123
|
# end
|
|
127
124
|
# end
|
|
128
|
-
def requires(*attrs, &block)
|
|
129
|
-
orig_attrs = attrs.clone
|
|
130
|
-
|
|
131
|
-
opts = attrs.extract_options!.clone
|
|
125
|
+
def requires(*attrs, **opts, &block)
|
|
132
126
|
opts[:presence] = { value: true, message: opts[:message] }
|
|
133
127
|
opts = @group.deep_merge(opts) if instance_variable_defined?(:@group) && @group
|
|
134
128
|
|
|
@@ -136,7 +130,7 @@ module Grape
|
|
|
136
130
|
require_required_and_optional_fields(attrs.first, opts)
|
|
137
131
|
else
|
|
138
132
|
validate_attributes(attrs, opts, &block)
|
|
139
|
-
block ? new_scope(
|
|
133
|
+
block ? new_scope(attrs, opts, &block) : push_declared_params(attrs, opts.slice(:as))
|
|
140
134
|
end
|
|
141
135
|
end
|
|
142
136
|
|
|
@@ -144,10 +138,7 @@ module Grape
|
|
|
144
138
|
# endpoint.
|
|
145
139
|
# @param (see #requires)
|
|
146
140
|
# @option (see #requires)
|
|
147
|
-
def optional(*attrs, &block)
|
|
148
|
-
orig_attrs = attrs.clone
|
|
149
|
-
|
|
150
|
-
opts = attrs.extract_options!.clone
|
|
141
|
+
def optional(*attrs, **opts, &block)
|
|
151
142
|
type = opts[:type]
|
|
152
143
|
opts = @group.deep_merge(opts) if instance_variable_defined?(:@group) && @group
|
|
153
144
|
|
|
@@ -162,7 +153,7 @@ module Grape
|
|
|
162
153
|
else
|
|
163
154
|
validate_attributes(attrs, opts, &block)
|
|
164
155
|
|
|
165
|
-
block ? new_scope(
|
|
156
|
+
block ? new_scope(attrs, opts, true, &block) : push_declared_params(attrs, opts.slice(:as))
|
|
166
157
|
end
|
|
167
158
|
end
|
|
168
159
|
|
|
@@ -251,7 +242,7 @@ module Grape
|
|
|
251
242
|
# @return hash of parameters relevant for the current scope
|
|
252
243
|
# @api private
|
|
253
244
|
def params(params)
|
|
254
|
-
params = @parent.params(params) if instance_variable_defined?(:@parent) && @parent
|
|
245
|
+
params = @parent.params_meeting_dependency.presence || @parent.params(params) if instance_variable_defined?(:@parent) && @parent
|
|
255
246
|
params = map_params(params, @element) if instance_variable_defined?(:@element) && @element
|
|
256
247
|
params
|
|
257
248
|
end
|