grape 2.1.2 → 2.2.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.
@@ -54,7 +54,7 @@ module Grape
54
54
 
55
55
  def fetch_formatter(headers, options)
56
56
  api_format = mime_types[headers[Rack::CONTENT_TYPE]] || env[Grape::Env::API_FORMAT]
57
- Grape::Formatter.formatter_for(api_format, **options)
57
+ Grape::Formatter.formatter_for(api_format, options[:formatters])
58
58
  end
59
59
 
60
60
  # Set the content type header for the API format if it is not already present.
@@ -97,7 +97,7 @@ module Grape
97
97
  fmt = request.media_type ? mime_types[request.media_type] : options[:default_format]
98
98
 
99
99
  throw :error, status: 415, message: "The provided content-type '#{request.media_type}' is not supported." unless content_type_for(fmt)
100
- parser = Grape::Parser.parser_for fmt, **options
100
+ parser = Grape::Parser.parser_for fmt, options[:parsers]
101
101
  if parser
102
102
  begin
103
103
  body = (env[Grape::Env::API_REQUEST_BODY] = parser.call(body, env))
@@ -17,45 +17,22 @@ module Grape
17
17
  # X-Cascade header to alert Grape::Router to attempt the next matched
18
18
  # route.
19
19
  class AcceptVersionHeader < Base
20
- def before
21
- potential_version = (env[Grape::Http::Headers::HTTP_ACCEPT_VERSION] || '').strip
22
-
23
- if strict? && potential_version.empty?
24
- # If no Accept-Version header:
25
- throw :error, status: 406, headers: error_headers, message: 'Accept-Version header must be set.'
26
- end
20
+ include VersionerHelpers
27
21
 
28
- return if potential_version.empty?
22
+ def before
23
+ potential_version = env[Grape::Http::Headers::HTTP_ACCEPT_VERSION]&.strip
24
+ not_acceptable!('Accept-Version header must be set.') if strict? && potential_version.blank?
29
25
 
30
- # If the requested version is not supported:
31
- throw :error, status: 406, headers: error_headers, message: 'The requested version is not supported.' unless versions.any? { |v| v.to_s == potential_version }
26
+ return if potential_version.blank?
32
27
 
28
+ not_acceptable!('The requested version is not supported.') unless potential_version_match?(potential_version)
33
29
  env[Grape::Env::API_VERSION] = potential_version
34
30
  end
35
31
 
36
32
  private
37
33
 
38
- def versions
39
- options[:versions] || []
40
- end
41
-
42
- def strict?
43
- options[:version_options] && options[:version_options][:strict]
44
- end
45
-
46
- # By default those errors contain an `X-Cascade` header set to `pass`, which allows nesting and stacking
47
- # of routes (see Grape::Router) for more information). To prevent
48
- # this behavior, and not add the `X-Cascade` header, one can set the `:cascade` option to `false`.
49
- def cascade?
50
- if options[:version_options]&.key?(:cascade)
51
- options[:version_options][:cascade]
52
- else
53
- true
54
- end
55
- end
56
-
57
- def error_headers
58
- cascade? ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {}
34
+ def not_acceptable!(message)
35
+ throw :error, status: 406, headers: error_headers, message: message
59
36
  end
60
37
  end
61
38
  end
@@ -22,17 +22,10 @@ module Grape
22
22
  # X-Cascade header to alert Grape::Router to attempt the next matched
23
23
  # route.
24
24
  class Header < Base
25
+ include VersionerHelpers
26
+
25
27
  def before
26
- handler = Grape::Util::AcceptHeaderHandler.new(
27
- accept_header: env[Grape::Http::Headers::HTTP_ACCEPT],
28
- versions: options[:versions],
29
- **options.fetch(:version_options) { {} }
30
- )
31
-
32
- handler.match_best_quality_media_type!(
33
- content_types: content_types,
34
- allowed_methods: env[Grape::Env::GRAPE_ALLOWED_METHODS]
35
- ) do |media_type|
28
+ match_best_quality_media_type! do |media_type|
36
29
  env.update(
37
30
  Grape::Env::API_TYPE => media_type.type,
38
31
  Grape::Env::API_SUBTYPE => media_type.subtype,
@@ -42,6 +35,98 @@ module Grape
42
35
  )
43
36
  end
44
37
  end
38
+
39
+ private
40
+
41
+ def match_best_quality_media_type!
42
+ return unless vendor
43
+
44
+ strict_header_checks!
45
+ media_type = Grape::Util::MediaType.best_quality(accept_header, available_media_types)
46
+ if media_type
47
+ yield media_type
48
+ else
49
+ fail!(allowed_methods)
50
+ end
51
+ end
52
+
53
+ def allowed_methods
54
+ env[Grape::Env::GRAPE_ALLOWED_METHODS]
55
+ end
56
+
57
+ def accept_header
58
+ env[Grape::Http::Headers::HTTP_ACCEPT]
59
+ end
60
+
61
+ def strict_header_checks!
62
+ return unless strict?
63
+
64
+ accept_header_check!
65
+ version_and_vendor_check!
66
+ end
67
+
68
+ def accept_header_check!
69
+ return if accept_header.present?
70
+
71
+ invalid_accept_header!('Accept header must be set.')
72
+ end
73
+
74
+ def version_and_vendor_check!
75
+ return if versions.blank? || version_and_vendor?
76
+
77
+ invalid_accept_header!('API vendor or version not found.')
78
+ end
79
+
80
+ def q_values_mime_types
81
+ @q_values_mime_types ||= Rack::Utils.q_values(accept_header).map(&:first)
82
+ end
83
+
84
+ def version_and_vendor?
85
+ q_values_mime_types.any? { |mime_type| Grape::Util::MediaType.match?(mime_type) }
86
+ end
87
+
88
+ def invalid_accept_header!(message)
89
+ raise Grape::Exceptions::InvalidAcceptHeader.new(message, error_headers)
90
+ end
91
+
92
+ def invalid_version_header!(message)
93
+ raise Grape::Exceptions::InvalidVersionHeader.new(message, error_headers)
94
+ end
95
+
96
+ def fail!(grape_allowed_methods)
97
+ return grape_allowed_methods if grape_allowed_methods.present?
98
+
99
+ media_types = q_values_mime_types.map { |mime_type| Grape::Util::MediaType.parse(mime_type) }
100
+ vendor_not_found!(media_types) || version_not_found!(media_types)
101
+ end
102
+
103
+ def vendor_not_found!(media_types)
104
+ return unless media_types.all? { |media_type| media_type&.vendor && media_type.vendor != vendor }
105
+
106
+ invalid_accept_header!('API vendor not found.')
107
+ end
108
+
109
+ def version_not_found!(media_types)
110
+ return unless media_types.all? { |media_type| media_type&.version && versions&.exclude?(media_type.version) }
111
+
112
+ invalid_version_header!('API version not found.')
113
+ end
114
+
115
+ def available_media_types
116
+ [].tap do |available_media_types|
117
+ base_media_type = "application/vnd.#{vendor}"
118
+ content_types.each_key do |extension|
119
+ versions&.reverse_each do |version|
120
+ available_media_types << "#{base_media_type}-#{version}+#{extension}"
121
+ available_media_types << "#{base_media_type}-#{version}"
122
+ end
123
+ available_media_types << "#{base_media_type}+#{extension}"
124
+ end
125
+
126
+ available_media_types << base_media_type
127
+ available_media_types.concat(content_types.values.flatten)
128
+ end
129
+ end
45
130
  end
46
131
  end
47
132
  end
@@ -19,31 +19,15 @@ module Grape
19
19
  #
20
20
  # env['api.version'] => 'v1'
21
21
  class Param < Base
22
- def default_options
23
- {
24
- version_options: {
25
- parameter: 'apiver'
26
- }
27
- }
28
- end
22
+ include VersionerHelpers
29
23
 
30
24
  def before
31
- potential_version = Rack::Utils.parse_nested_query(env[Rack::QUERY_STRING])[paramkey]
32
- return if potential_version.nil?
25
+ potential_version = Rack::Utils.parse_nested_query(env[Rack::QUERY_STRING])[parameter_key]
26
+ return if potential_version.blank?
33
27
 
34
- throw :error, status: 404, message: '404 API Version Not Found', headers: { Grape::Http::Headers::X_CASCADE => 'pass' } if options[:versions] && !options[:versions].find { |v| v.to_s == potential_version }
28
+ version_not_found! unless potential_version_match?(potential_version)
35
29
  env[Grape::Env::API_VERSION] = potential_version
36
- env[Rack::RACK_REQUEST_QUERY_HASH].delete(paramkey) if env.key? Rack::RACK_REQUEST_QUERY_HASH
37
- end
38
-
39
- private
40
-
41
- def paramkey
42
- version_options[:parameter] || default_options[:version_options][:parameter]
43
- end
44
-
45
- def version_options
46
- options[:version_options]
30
+ env[Rack::RACK_REQUEST_QUERY_HASH].delete(parameter_key) if env.key? Rack::RACK_REQUEST_QUERY_HASH
47
31
  end
48
32
  end
49
33
  end
@@ -17,44 +17,24 @@ module Grape
17
17
  # env['api.version'] => 'v1'
18
18
  #
19
19
  class Path < Base
20
- def default_options
21
- {
22
- pattern: /.*/i
23
- }
24
- end
20
+ include VersionerHelpers
25
21
 
26
22
  def before
27
- path = env[Rack::PATH_INFO].dup
28
- path.sub!(mount_path, '') if mounted_path?(path)
23
+ path_info = Grape::Router.normalize_path(env[Rack::PATH_INFO])
24
+ return if path_info == '/'
29
25
 
30
- if prefix && path.index(prefix) == 0 # rubocop:disable all
31
- path.sub!(prefix, '')
32
- path = Grape::Router.normalize_path(path)
26
+ [mount_path, Grape::Router.normalize_path(prefix)].each do |path|
27
+ path_info.delete_prefix!(path) if path.present? && path != '/' && path_info.start_with?(path)
33
28
  end
34
29
 
35
- pieces = path.split('/')
36
- potential_version = pieces[1]
37
- return unless potential_version&.match?(options[:pattern])
38
-
39
- throw :error, status: 404, message: '404 API Version Not Found' if options[:versions] && !options[:versions].find { |v| v.to_s == potential_version }
40
- env[Grape::Env::API_VERSION] = potential_version
41
- end
42
-
43
- private
30
+ slash_position = path_info.index('/', 1) # omit the first one
31
+ return unless slash_position
44
32
 
45
- def mounted_path?(path)
46
- return false unless mount_path && path.start_with?(mount_path)
33
+ potential_version = path_info[1..slash_position - 1]
34
+ return unless potential_version.match?(pattern)
47
35
 
48
- rest = path.slice(mount_path.length..-1)
49
- rest.start_with?('/') || rest.empty?
50
- end
51
-
52
- def mount_path
53
- @mount_path ||= options[:mount_path] && options[:mount_path] != '/' ? options[:mount_path] : ''
54
- end
55
-
56
- def prefix
57
- Grape::Router.normalize_path(options[:prefix].to_s) if options[:prefix]
36
+ version_not_found! unless potential_version_match?(potential_version)
37
+ env[Grape::Env::API_VERSION] = potential_version
58
38
  end
59
39
  end
60
40
  end
@@ -4,30 +4,21 @@
4
4
  # on the requests. The current methods for determining version are:
5
5
  #
6
6
  # :header - version from HTTP Accept header.
7
+ # :accept_version_header - version from HTTP Accept-Version header
7
8
  # :path - version from uri. e.g. /v1/resource
8
9
  # :param - version from uri query string, e.g. /v1/resource?apiver=v1
9
- #
10
10
  # See individual classes for details.
11
11
  module Grape
12
12
  module Middleware
13
13
  module Versioner
14
14
  module_function
15
15
 
16
- # @param strategy [Symbol] :path, :header or :param
16
+ # @param strategy [Symbol] :path, :header, :accept_version_header or :param
17
17
  # @return a middleware class based on strategy
18
18
  def using(strategy)
19
- case strategy
20
- when :path
21
- Path
22
- when :header
23
- Header
24
- when :param
25
- Param
26
- when :accept_version_header
27
- AcceptVersionHeader
28
- else
29
- raise Grape::Exceptions::InvalidVersionerOption.new(strategy)
30
- end
19
+ Grape::Middleware::Versioner.const_get(:"#{strategy.to_s.camelize}")
20
+ rescue NameError
21
+ raise Grape::Exceptions::InvalidVersionerOption, strategy
31
22
  end
32
23
  end
33
24
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grape
4
+ module Middleware
5
+ module VersionerHelpers
6
+ DEFAULT_PATTERN = /.*/i.freeze
7
+ DEFAULT_PARAMETER = 'apiver'
8
+
9
+ def default_options
10
+ {
11
+ versions: nil,
12
+ prefix: nil,
13
+ mount_path: nil,
14
+ pattern: DEFAULT_PATTERN,
15
+ version_options: {
16
+ strict: false,
17
+ cascade: true,
18
+ parameter: DEFAULT_PARAMETER
19
+ }
20
+ }
21
+ end
22
+
23
+ def versions
24
+ options[:versions]
25
+ end
26
+
27
+ def prefix
28
+ options[:prefix]
29
+ end
30
+
31
+ def mount_path
32
+ options[:mount_path]
33
+ end
34
+
35
+ def pattern
36
+ options[:pattern]
37
+ end
38
+
39
+ def version_options
40
+ options[:version_options]
41
+ end
42
+
43
+ def strict?
44
+ version_options[:strict]
45
+ end
46
+
47
+ # By default those errors contain an `X-Cascade` header set to `pass`, which allows nesting and stacking
48
+ # of routes (see Grape::Router) for more information). To prevent
49
+ # this behavior, and not add the `X-Cascade` header, one can set the `:cascade` option to `false`.
50
+ def cascade?
51
+ version_options[:cascade]
52
+ end
53
+
54
+ def parameter_key
55
+ version_options[:parameter]
56
+ end
57
+
58
+ def vendor
59
+ version_options[:vendor]
60
+ end
61
+
62
+ def error_headers
63
+ cascade? ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {}
64
+ end
65
+
66
+ def potential_version_match?(potential_version)
67
+ versions.blank? || versions.any? { |v| v.to_s == potential_version }
68
+ end
69
+
70
+ def version_not_found!
71
+ throw :error, status: 404, message: '404 API Version Not Found', headers: { Grape::Http::Headers::X_CASCADE => 'pass' }
72
+ end
73
+ end
74
+ end
75
+ end
data/lib/grape/parser.rb CHANGED
@@ -2,32 +2,16 @@
2
2
 
3
3
  module Grape
4
4
  module Parser
5
- extend Util::Registrable
5
+ module_function
6
6
 
7
- class << self
8
- def builtin_parsers
9
- @builtin_parsers ||= {
10
- json: Grape::Parser::Json,
11
- jsonapi: Grape::Parser::Json,
12
- xml: Grape::Parser::Xml
13
- }
14
- end
7
+ DEFAULTS = {
8
+ json: Grape::Parser::Json,
9
+ jsonapi: Grape::Parser::Json,
10
+ xml: Grape::Parser::Xml
11
+ }.freeze
15
12
 
16
- def parsers(**options)
17
- builtin_parsers.merge(default_elements).merge!(options[:parsers] || {})
18
- end
19
-
20
- def parser_for(api_format, **options)
21
- spec = parsers(**options)[api_format]
22
- case spec
23
- when nil
24
- nil
25
- when Symbol
26
- method(spec)
27
- else
28
- spec
29
- end
30
- end
13
+ def parser_for(format, parsers = nil)
14
+ parsers&.key?(format) ? parsers[format] : DEFAULTS[format]
31
15
  end
32
16
  end
33
17
  end
@@ -190,7 +190,13 @@ module Grape
190
190
  #
191
191
  # @return [Array<Symbol>] the nesting/path of the current parameter scope
192
192
  def full_path
193
- nested? ? @parent.full_path + [@element] : []
193
+ if nested?
194
+ (@parent.full_path + [@element])
195
+ elsif lateral?
196
+ @parent.full_path
197
+ else
198
+ []
199
+ end
194
200
  end
195
201
 
196
202
  private
@@ -7,20 +7,25 @@ module Grape
7
7
  def initialize(attrs, options, required, scope, **opts)
8
8
  @min = options[:min]
9
9
  @max = options[:max]
10
+ @is = options[:is]
10
11
 
11
12
  super
12
13
 
13
14
  raise ArgumentError, 'min must be an integer greater than or equal to zero' if !@min.nil? && (!@min.is_a?(Integer) || @min.negative?)
14
15
  raise ArgumentError, 'max must be an integer greater than or equal to zero' if !@max.nil? && (!@max.is_a?(Integer) || @max.negative?)
15
16
  raise ArgumentError, "min #{@min} cannot be greater than max #{@max}" if !@min.nil? && !@max.nil? && @min > @max
17
+
18
+ return if @is.nil?
19
+ raise ArgumentError, 'is must be an integer greater than zero' if !@is.is_a?(Integer) || !@is.positive?
20
+ raise ArgumentError, 'is cannot be combined with min or max' if !@min.nil? || !@max.nil?
16
21
  end
17
22
 
18
23
  def validate_param!(attr_name, params)
19
24
  param = params[attr_name]
20
25
 
21
- raise ArgumentError, "parameter #{param} does not support #length" unless param.respond_to?(:length)
26
+ return unless param.respond_to?(:length)
22
27
 
23
- return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max)
28
+ return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) || (!@is.nil? && param.length != @is)
24
29
 
25
30
  raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: build_message)
26
31
  end
@@ -32,8 +37,10 @@ module Grape
32
37
  format I18n.t(:length, scope: 'grape.errors.messages'), min: @min, max: @max
33
38
  elsif @min
34
39
  format I18n.t(:length_min, scope: 'grape.errors.messages'), min: @min
35
- else
40
+ elsif @max
36
41
  format I18n.t(:length_max, scope: 'grape.errors.messages'), max: @max
42
+ else
43
+ format I18n.t(:length_is, scope: 'grape.errors.messages'), is: @is
37
44
  end
38
45
  end
39
46
  end
data/lib/grape/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Grape
4
4
  # The current version of Grape.
5
- VERSION = '2.1.2'
5
+ VERSION = '2.2.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-28 00:00:00.000000000 Z
11
+ date: 2024-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -172,6 +172,7 @@ files:
172
172
  - lib/grape/middleware/versioner/header.rb
173
173
  - lib/grape/middleware/versioner/param.rb
174
174
  - lib/grape/middleware/versioner/path.rb
175
+ - lib/grape/middleware/versioner_helpers.rb
175
176
  - lib/grape/namespace.rb
176
177
  - lib/grape/parser.rb
177
178
  - lib/grape/parser/json.rb
@@ -189,7 +190,6 @@ files:
189
190
  - lib/grape/serve_stream/sendfile_response.rb
190
191
  - lib/grape/serve_stream/stream_response.rb
191
192
  - lib/grape/types/invalid_value.rb
192
- - lib/grape/util/accept_header_handler.rb
193
193
  - lib/grape/util/base_inheritable.rb
194
194
  - lib/grape/util/cache.rb
195
195
  - lib/grape/util/endpoint_configuration.rb
@@ -203,7 +203,6 @@ files:
203
203
  - lib/grape/util/lazy/value_enumerable.rb
204
204
  - lib/grape/util/lazy/value_hash.rb
205
205
  - lib/grape/util/media_type.rb
206
- - lib/grape/util/registrable.rb
207
206
  - lib/grape/util/reverse_stackable_values.rb
208
207
  - lib/grape/util/stackable_values.rb
209
208
  - lib/grape/util/strict_hash_configuration.rb
@@ -251,9 +250,10 @@ licenses:
251
250
  - MIT
252
251
  metadata:
253
252
  bug_tracker_uri: https://github.com/ruby-grape/grape/issues
254
- changelog_uri: https://github.com/ruby-grape/grape/blob/v2.1.2/CHANGELOG.md
255
- documentation_uri: https://www.rubydoc.info/gems/grape/2.1.2
256
- source_code_uri: https://github.com/ruby-grape/grape/tree/v2.1.2
253
+ changelog_uri: https://github.com/ruby-grape/grape/blob/v2.2.0/CHANGELOG.md
254
+ documentation_uri: https://www.rubydoc.info/gems/grape/2.2.0
255
+ source_code_uri: https://github.com/ruby-grape/grape/tree/v2.2.0
256
+ rubygems_mfa_required: 'true'
257
257
  post_install_message:
258
258
  rdoc_options: []
259
259
  require_paths:
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Util
5
- class AcceptHeaderHandler
6
- attr_reader :accept_header, :versions, :vendor, :strict, :cascade
7
-
8
- def initialize(accept_header:, versions:, **options)
9
- @accept_header = accept_header
10
- @versions = versions
11
- @vendor = options.fetch(:vendor, nil)
12
- @strict = options.fetch(:strict, false)
13
- @cascade = options.fetch(:cascade, true)
14
- end
15
-
16
- def match_best_quality_media_type!(content_types: Grape::ContentTypes::CONTENT_TYPES, allowed_methods: nil)
17
- return unless vendor
18
-
19
- strict_header_checks!
20
- media_type = Grape::Util::MediaType.best_quality(accept_header, available_media_types(content_types))
21
- if media_type
22
- yield media_type
23
- else
24
- fail!(allowed_methods)
25
- end
26
- end
27
-
28
- private
29
-
30
- def strict_header_checks!
31
- return unless strict
32
-
33
- accept_header_check!
34
- version_and_vendor_check!
35
- end
36
-
37
- def accept_header_check!
38
- return if accept_header.present?
39
-
40
- invalid_accept_header!('Accept header must be set.')
41
- end
42
-
43
- def version_and_vendor_check!
44
- return if versions.blank? || version_and_vendor?
45
-
46
- invalid_accept_header!('API vendor or version not found.')
47
- end
48
-
49
- def q_values_mime_types
50
- @q_values_mime_types ||= Rack::Utils.q_values(accept_header).map(&:first)
51
- end
52
-
53
- def version_and_vendor?
54
- q_values_mime_types.any? { |mime_type| Grape::Util::MediaType.match?(mime_type) }
55
- end
56
-
57
- def invalid_accept_header!(message)
58
- raise Grape::Exceptions::InvalidAcceptHeader.new(message, error_headers)
59
- end
60
-
61
- def invalid_version_header!(message)
62
- raise Grape::Exceptions::InvalidVersionHeader.new(message, error_headers)
63
- end
64
-
65
- def fail!(grape_allowed_methods)
66
- return grape_allowed_methods if grape_allowed_methods.present?
67
-
68
- media_types = q_values_mime_types.map { |mime_type| Grape::Util::MediaType.parse(mime_type) }
69
- vendor_not_found!(media_types) || version_not_found!(media_types)
70
- end
71
-
72
- def vendor_not_found!(media_types)
73
- return unless media_types.all? { |media_type| media_type&.vendor && media_type.vendor != vendor }
74
-
75
- invalid_accept_header!('API vendor not found.')
76
- end
77
-
78
- def version_not_found!(media_types)
79
- return unless media_types.all? { |media_type| media_type&.version && versions.exclude?(media_type.version) }
80
-
81
- invalid_version_header!('API version not found.')
82
- end
83
-
84
- def error_headers
85
- cascade ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {}
86
- end
87
-
88
- def available_media_types(content_types)
89
- [].tap do |available_media_types|
90
- base_media_type = "application/vnd.#{vendor}"
91
- content_types.each_key do |extension|
92
- versions&.reverse_each do |version|
93
- available_media_types << "#{base_media_type}-#{version}+#{extension}"
94
- available_media_types << "#{base_media_type}-#{version}"
95
- end
96
- available_media_types << "#{base_media_type}+#{extension}"
97
- end
98
-
99
- available_media_types << base_media_type
100
- available_media_types.concat(content_types.values.flatten)
101
- end
102
- end
103
- end
104
- end
105
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Util
5
- module Registrable
6
- def default_elements
7
- @default_elements ||= {}
8
- end
9
-
10
- def register(format, element)
11
- default_elements[format] = element unless default_elements[format]
12
- end
13
- end
14
- end
15
- end