grape 3.3.4 → 4.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 +128 -0
- data/CONTRIBUTING.md +16 -0
- data/README.md +208 -8
- data/UPGRADING.md +756 -6
- data/lib/grape/api/instance.rb +40 -33
- data/lib/grape/content_types.rb +47 -1
- data/lib/grape/dry_types.rb +1 -1
- data/lib/grape/dsl/callbacks.rb +3 -9
- data/lib/grape/dsl/declared.rb +4 -4
- data/lib/grape/dsl/desc.rb +18 -8
- data/lib/grape/dsl/entity.rb +37 -19
- data/lib/grape/dsl/helpers.rb +3 -3
- data/lib/grape/dsl/inside_route.rb +20 -8
- data/lib/grape/dsl/middleware.rb +3 -3
- data/lib/grape/dsl/parameters.rb +54 -28
- data/lib/grape/dsl/request_response.rb +37 -39
- data/lib/grape/dsl/rescue_options.rb +6 -5
- data/lib/grape/dsl/routing.rb +116 -49
- data/lib/grape/dsl/settings.rb +1 -1
- data/lib/grape/dsl/validations.rb +3 -3
- data/lib/grape/dsl/version_options.rb +3 -3
- data/lib/grape/endpoint/options.rb +13 -7
- data/lib/grape/endpoint.rb +141 -118
- data/lib/grape/env.rb +7 -0
- data/lib/grape/error_formatter/base.rb +6 -5
- data/lib/grape/error_formatter.rb +6 -2
- data/lib/grape/exceptions/error_response.rb +4 -1
- data/lib/grape/exceptions/unknown_error_formatter.rb +11 -0
- data/lib/grape/exceptions/validation.rb +9 -8
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +1 -0
- data/lib/grape/locale/en.yml +1 -0
- data/lib/grape/middleware/auth/dsl.rb +5 -33
- data/lib/grape/middleware/error.rb +153 -46
- data/lib/grape/middleware/formatter.rb +95 -26
- data/lib/grape/middleware/precomputed_content_types.rb +12 -7
- data/lib/grape/middleware/stack.rb +13 -4
- data/lib/grape/middleware/versioner/base.rb +3 -9
- data/lib/grape/middleware/versioner/path.rb +49 -7
- data/lib/grape/namespace.rb +3 -2
- data/lib/grape/path.rb +8 -69
- data/lib/grape/precompiled_json.rb +50 -0
- data/lib/grape/request.rb +36 -4
- data/lib/grape/router/base_route.rb +47 -10
- data/lib/grape/router/greedy_route.rb +5 -1
- data/lib/grape/router/pattern/path.rb +78 -0
- data/lib/grape/router/pattern.rb +60 -14
- data/lib/grape/router/route.rb +62 -10
- data/lib/grape/router.rb +100 -57
- data/lib/grape/serve_stream/file_body.rb +6 -0
- data/lib/grape/serve_stream/stream_response.rb +6 -0
- data/lib/grape/util/api_description.rb +10 -1
- data/lib/grape/util/cache.rb +21 -2
- data/lib/grape/util/deep_freeze.rb +1 -2
- data/lib/grape/util/freeze_on_new.rb +20 -0
- data/lib/grape/util/inheritable_setting.rb +751 -37
- data/lib/grape/util/media_type.rb +10 -3
- data/lib/grape/util/path_normalizer.rb +12 -9
- data/lib/grape/util/registry.rb +12 -2
- data/lib/grape/util/shadowed_rescue_handlers.rb +49 -0
- data/lib/grape/util/stackable_values.rb +32 -6
- data/lib/grape/validations/attributes_iterator.rb +21 -4
- data/lib/grape/validations/contract_scope.rb +8 -7
- data/lib/grape/validations/oneof_collector.rb +6 -10
- data/lib/grape/validations/params_documentation.rb +2 -2
- data/lib/grape/validations/params_scope.rb +66 -26
- data/lib/grape/validations/single_attribute_iterator.rb +5 -3
- data/lib/grape/validations/types/array_coercer.rb +4 -6
- data/lib/grape/validations/types/custom_type_coercer.rb +7 -1
- data/lib/grape/validations/types/dry_type_coercer.rb +3 -1
- data/lib/grape/validations/types/json.rb +1 -3
- data/lib/grape/validations/types/multiple_type_coercer.rb +5 -3
- data/lib/grape/validations/types/primitive_coercer.rb +12 -9
- data/lib/grape/validations/types/variant_collection_coercer.rb +8 -3
- data/lib/grape/validations/types.rb +5 -5
- data/lib/grape/validations/validations_spec.rb +14 -4
- data/lib/grape/validations/validators/base.rb +4 -7
- data/lib/grape/validations/validators/coerce_validator.rb +8 -2
- data/lib/grape/validations/validators/contract_scope_validator.rb +2 -1
- data/lib/grape/validations/validators/length_validator.rb +4 -2
- data/lib/grape/validations/validators/oneof_validator.rb +2 -0
- data/lib/grape/validations/validators/same_as_validator.rb +1 -0
- data/lib/grape/version.rb +2 -1
- data/lib/grape.rb +23 -2
- metadata +10 -9
- data/lib/grape/middleware/deprecated_options_hash_access.rb +0 -19
- data/lib/grape/util/base_inheritable.rb +0 -43
- data/lib/grape/util/inheritable_values.rb +0 -33
- data/lib/grape/util/reverse_stackable_values.rb +0 -15
|
@@ -7,10 +7,18 @@ module Grape
|
|
|
7
7
|
# initialization. When +strict+ is true, it doesn't coerce a value but check
|
|
8
8
|
# that it has the proper type.
|
|
9
9
|
class PrimitiveCoercer < DryTypeCoercer
|
|
10
|
+
# The input classes Virtus refused for a given declared type, keyed by
|
|
11
|
+
# that type. Resolved once in #initialize rather than re-derived from
|
|
12
|
+
# +type+ on every value: the answer only ever depends on the
|
|
13
|
+
# declaration, and every coerced attribute of every request asks.
|
|
14
|
+
REJECTED_INPUTS = { String => [Array, Hash].freeze, Hash => [String].freeze }.freeze
|
|
15
|
+
|
|
10
16
|
def initialize(type, strict: false)
|
|
11
17
|
super
|
|
12
18
|
|
|
13
19
|
@coercer = cache_coercer[type]
|
|
20
|
+
@rejected_inputs = REJECTED_INPUTS[type]
|
|
21
|
+
@treat_empty_as_nil = type != String
|
|
14
22
|
end
|
|
15
23
|
|
|
16
24
|
def call(val)
|
|
@@ -29,21 +37,16 @@ module Grape
|
|
|
29
37
|
# but Virtus wouldn't accept it. So, this method only exists to not introduce
|
|
30
38
|
# breaking changes.
|
|
31
39
|
def reject?(val)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
when String
|
|
36
|
-
type == Hash
|
|
37
|
-
else
|
|
38
|
-
false
|
|
39
|
-
end
|
|
40
|
+
return false unless @rejected_inputs
|
|
41
|
+
|
|
42
|
+
@rejected_inputs.any? { |klass| val.is_a?(klass) }
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
# Dry-Types treats an empty string as invalid. However, Grape considers an empty string as
|
|
43
46
|
# absence of a value and coerces it into nil. See a discussion there
|
|
44
47
|
# https://github.com/ruby-grape/grape/pull/2045
|
|
45
48
|
def treat_as_nil?(val)
|
|
46
|
-
val == ''
|
|
49
|
+
@treat_empty_as_nil && val == ''
|
|
47
50
|
end
|
|
48
51
|
end
|
|
49
52
|
end
|
|
@@ -6,6 +6,11 @@ module Grape
|
|
|
6
6
|
# This class wraps {MultipleTypeCoercer}, for use with collections
|
|
7
7
|
# that allow members of more than one type.
|
|
8
8
|
class VariantCollectionCoercer
|
|
9
|
+
extend Grape::Util::FreezeOnNew
|
|
10
|
+
|
|
11
|
+
# @return [Array<Class>,Set<Class>] the member types as declared in the DSL
|
|
12
|
+
attr_reader :types
|
|
13
|
+
|
|
9
14
|
# Construct a new coercer that will attempt to coerce
|
|
10
15
|
# a list of values such that all members are of one of
|
|
11
16
|
# the given types. The container may also optionally be
|
|
@@ -43,15 +48,15 @@ module Grape
|
|
|
43
48
|
def call(value)
|
|
44
49
|
return unless value.is_a? Array
|
|
45
50
|
|
|
46
|
-
|
|
51
|
+
coerced =
|
|
47
52
|
if @method
|
|
48
53
|
@method.call(value)
|
|
49
54
|
else
|
|
50
55
|
value.map { |v| @member_coercer.call(v) }
|
|
51
56
|
end
|
|
52
|
-
return Set.new
|
|
57
|
+
return Set.new coerced if @types.is_a? Set
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
coerced
|
|
55
60
|
end
|
|
56
61
|
end
|
|
57
62
|
end
|
|
@@ -162,20 +162,20 @@ module Grape
|
|
|
162
162
|
|
|
163
163
|
def create_coercer_instance(type, method, strict)
|
|
164
164
|
# map_special doesn't recurse into collections — applied only to the top-level type here.
|
|
165
|
-
|
|
165
|
+
mapped = map_special(type)
|
|
166
166
|
|
|
167
167
|
# Multiply-typed parameters, e.g. types: [Integer, String].
|
|
168
|
-
return MultipleTypeCoercer.new(
|
|
168
|
+
return MultipleTypeCoercer.new(mapped, method) if multiple?(mapped)
|
|
169
169
|
|
|
170
170
|
# User-supplied coercion method, or a custom type with its own #parse.
|
|
171
|
-
return CustomTypeCoercer.new(
|
|
171
|
+
return CustomTypeCoercer.new(mapped, method) if method || custom?(mapped)
|
|
172
172
|
|
|
173
173
|
# Array/Set of a custom type — CustomTypeCoercer already handles single
|
|
174
174
|
# custom types when an explicit coercion method is supplied.
|
|
175
|
-
return CustomTypeCollectionCoercer.new(map_special(
|
|
175
|
+
return CustomTypeCollectionCoercer.new(map_special(mapped.first), set: mapped.is_a?(Set)) if collection_of_custom?(mapped)
|
|
176
176
|
|
|
177
177
|
# Fallback: let dry-types handle primitives, structures, and known specials.
|
|
178
|
-
DryTypeCoercer.coercer_instance_for(
|
|
178
|
+
DryTypeCoercer.coercer_instance_for(mapped, strict:)
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
class CoercerCache < Grape::Util::Cache
|
|
@@ -51,7 +51,7 @@ module Grape
|
|
|
51
51
|
@allow_blank = resolve_value(raw[:allow_blank])
|
|
52
52
|
@fail_fast = raw[:fail_fast] || false
|
|
53
53
|
|
|
54
|
-
@guessed_coerce_type = guess_coerce_type(
|
|
54
|
+
@guessed_coerce_type = guess_coerce_type(declared_coerce_type, @values, @except_values)
|
|
55
55
|
@shared_opts = { allow_blank: @allow_blank, fail_fast: @fail_fast }.freeze
|
|
56
56
|
@validator_entries = build_validator_entries(raw)
|
|
57
57
|
|
|
@@ -97,13 +97,13 @@ module Grape
|
|
|
97
97
|
def validate_value_coercion(coerce_type, *values_list)
|
|
98
98
|
return unless coerce_type
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
element_type = coerce_type.is_a?(Enumerable) ? coerce_type.first : coerce_type
|
|
101
101
|
values_list.each do |values|
|
|
102
102
|
next if !values || values.is_a?(Proc)
|
|
103
103
|
|
|
104
104
|
value_types = values.is_a?(Range) ? [values.begin, values.end].compact : values
|
|
105
|
-
value_types = value_types.map { |type| Grape::API::Boolean.build(type) } if
|
|
106
|
-
raise Grape::Exceptions::IncompatibleOptionValues.new(:type,
|
|
105
|
+
value_types = value_types.map { |type| Grape::API::Boolean.build(type) } if element_type == Grape::API::Boolean
|
|
106
|
+
raise Grape::Exceptions::IncompatibleOptionValues.new(:type, element_type, :values, values) unless value_types.all?(element_type)
|
|
107
107
|
end
|
|
108
108
|
end
|
|
109
109
|
|
|
@@ -140,6 +140,16 @@ module Grape
|
|
|
140
140
|
opt.is_a?(Hash) ? opt[:value] : opt
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
+
# The type as written in the DSL. Identical to +@coerce_type+ except for
|
|
144
|
+
# a multiple-type declaration (+type: [Integer, String]+), where
|
|
145
|
+
# {#parse_coerce} wraps the declared list in a
|
|
146
|
+
# {Types::VariantCollectionCoercer} for runtime coercion — the
|
|
147
|
+
# definition-time coherence checks need the list back, since the wrapper
|
|
148
|
+
# matches nothing under +===+.
|
|
149
|
+
def declared_coerce_type
|
|
150
|
+
@coerce_type.is_a?(Types::VariantCollectionCoercer) ? @coerce_type.types : @coerce_type
|
|
151
|
+
end
|
|
152
|
+
|
|
143
153
|
def guess_coerce_type(coerce_type, *values_list)
|
|
144
154
|
return coerce_type unless coerce_type == Array
|
|
145
155
|
|
|
@@ -13,6 +13,7 @@ module Grape
|
|
|
13
13
|
# (e.g. +memoize+, <tt>||=</tt>) will raise +FrozenError+ at request time.
|
|
14
14
|
class Base
|
|
15
15
|
extend Forwardable
|
|
16
|
+
extend Grape::Util::FreezeOnNew
|
|
16
17
|
include Grape::Util::Translation
|
|
17
18
|
|
|
18
19
|
attr_reader :attrs
|
|
@@ -45,10 +46,6 @@ module Grape
|
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
def new(...)
|
|
49
|
-
super.freeze
|
|
50
|
-
end
|
|
51
|
-
|
|
52
49
|
def inherited(klass)
|
|
53
50
|
super
|
|
54
51
|
Validations.register(klass)
|
|
@@ -67,7 +64,6 @@ module Grape
|
|
|
67
64
|
def initialize(attrs, options, required, scope, opts)
|
|
68
65
|
@attrs = Array(attrs).freeze
|
|
69
66
|
@options = Grape::Util::DeepFreeze.deep_freeze(options)
|
|
70
|
-
@option = @options # TODO: remove in next major release
|
|
71
67
|
@required = required
|
|
72
68
|
@scope = scope
|
|
73
69
|
@opts = SharedOptions.new(**opts.slice(:allow_blank, :fail_fast))
|
|
@@ -81,9 +77,10 @@ module Grape
|
|
|
81
77
|
# @raise [Grape::Exceptions::Validation] if validation failed
|
|
82
78
|
# @return [void]
|
|
83
79
|
def validate(request)
|
|
84
|
-
|
|
80
|
+
params = request.params
|
|
81
|
+
return unless scope.should_validate?(params)
|
|
85
82
|
|
|
86
|
-
validate!(
|
|
83
|
+
validate!(params)
|
|
87
84
|
end
|
|
88
85
|
|
|
89
86
|
# Validates a given parameter hash.
|
|
@@ -21,10 +21,16 @@ module Grape
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# The attribute is read once and held: +coerce_value+ only ever sees the
|
|
25
|
+
# value, never the Hash, so the two further reads the identity check
|
|
26
|
+
# used to make came back with the same object -- through a
|
|
27
|
+
# HashWithIndifferentAccess key conversion each time, for every coerced
|
|
28
|
+
# attribute of every request.
|
|
24
29
|
def validate_param!(attr_name, params)
|
|
25
30
|
validation_error!(attr_name) unless hash_like?(params)
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
value = params[attr_name]
|
|
33
|
+
new_value = coerce_value(value)
|
|
28
34
|
|
|
29
35
|
validation_error!(attr_name, new_value.message || exception_message) if new_value.is_a?(Types::InvalidValue)
|
|
30
36
|
|
|
@@ -37,7 +43,7 @@ module Grape
|
|
|
37
43
|
# h[:list] = list
|
|
38
44
|
# h
|
|
39
45
|
# => #<Hashie::Mash list=[1, 2, 3, 4]>
|
|
40
|
-
return if
|
|
46
|
+
return if value.instance_of?(new_value.class) && value == new_value
|
|
41
47
|
|
|
42
48
|
params[attr_name] = new_value
|
|
43
49
|
end
|
|
@@ -10,7 +10,7 @@ module Grape
|
|
|
10
10
|
@min, @max, @is = options.values_at(:min, :max, :is)
|
|
11
11
|
validate_boundary!(:min, @min)
|
|
12
12
|
validate_boundary!(:max, @max)
|
|
13
|
-
raise ArgumentError, "min
|
|
13
|
+
raise ArgumentError, "min `#{@min}` cannot be greater than max `#{@max}`" if @min && @max && @min > @max
|
|
14
14
|
|
|
15
15
|
return if @is.nil?
|
|
16
16
|
raise ArgumentError, 'is must be an integer greater than zero' unless @is.is_a?(Integer) && @is.positive?
|
|
@@ -18,6 +18,8 @@ module Grape
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def validate_param!(attr_name, params)
|
|
21
|
+
return unless hash_like?(params)
|
|
22
|
+
|
|
21
23
|
param = params[attr_name]
|
|
22
24
|
|
|
23
25
|
return unless param.respond_to?(:length)
|
|
@@ -40,7 +42,7 @@ module Grape
|
|
|
40
42
|
private
|
|
41
43
|
|
|
42
44
|
def validate_boundary!(name, val)
|
|
43
|
-
raise ArgumentError, "
|
|
45
|
+
raise ArgumentError, "`#{name}` must be an integer greater than or equal to zero" if !val.nil? && (!val.is_a?(Integer) || val.negative?)
|
|
44
46
|
end
|
|
45
47
|
end
|
|
46
48
|
end
|
data/lib/grape/version.rb
CHANGED
data/lib/grape.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'logger'
|
|
4
|
+
require 'monitor'
|
|
4
5
|
require 'active_support'
|
|
5
6
|
require 'active_support/isolated_execution_state'
|
|
6
7
|
require 'active_support/core_ext/array/conversions' # to_xml
|
|
@@ -41,7 +42,12 @@ loader.inflector.inflect(
|
|
|
41
42
|
'dsl' => 'DSL'
|
|
42
43
|
)
|
|
43
44
|
railtie = "#{__dir__}/grape/railtie.rb"
|
|
44
|
-
|
|
45
|
+
# Grape::Testing is a test-environment helper -- it extends Grape::Endpoint with
|
|
46
|
+
# `before_each` and prepends a hook to Grape::Endpoint#run. It is documented as
|
|
47
|
+
# opt-in (`require 'grape/testing'`), which eager loading quietly contradicted
|
|
48
|
+
# by installing it in every process.
|
|
49
|
+
testing = "#{__dir__}/grape/testing.rb"
|
|
50
|
+
loader.do_not_eager_load(railtie, testing)
|
|
45
51
|
loader.setup
|
|
46
52
|
|
|
47
53
|
I18n.load_path << File.expand_path('grape/locale/en.yml', __dir__)
|
|
@@ -52,9 +58,17 @@ module Grape
|
|
|
52
58
|
setting :param_builder, default: :hash_with_indifferent_access
|
|
53
59
|
setting :lint, default: false
|
|
54
60
|
setting :warn_on_helper_overrides, default: false
|
|
61
|
+
# Let an error response that cannot be rendered propagate out of the
|
|
62
|
+
# middleware stack instead of being answered with a failsafe 500.
|
|
63
|
+
setting :raise_rendering_errors, default: false
|
|
64
|
+
|
|
65
|
+
# The HTTP QUERY method (RFC 10008): a safe, idempotent request whose content
|
|
66
|
+
# carries the query. Rack has no constant for it yet, hence the literal.
|
|
67
|
+
QUERY = 'QUERY'
|
|
55
68
|
|
|
56
69
|
HTTP_SUPPORTED_METHODS = [
|
|
57
70
|
Rack::GET,
|
|
71
|
+
QUERY,
|
|
58
72
|
Rack::POST,
|
|
59
73
|
Rack::PUT,
|
|
60
74
|
Rack::PATCH,
|
|
@@ -81,8 +95,15 @@ module Grape
|
|
|
81
95
|
]
|
|
82
96
|
end.freeze
|
|
83
97
|
|
|
98
|
+
# The deprecation horizon is the version a deprecation announces as its
|
|
99
|
+
# removal point, so it is the *next* major rather than the current one, and
|
|
100
|
+
# it is derived from VERSION rather than written out. Written out, it went
|
|
101
|
+
# stale: it said '2.0' from 2023 (#2353) through all of 2.x, 3.x and 4.x, so
|
|
102
|
+
# a method deprecated through this deprecator announced a removal version
|
|
103
|
+
# that had already shipped, and every custom `behavior` lambda -- how a Rails
|
|
104
|
+
# app consumes deprecations -- was handed the same wrong number.
|
|
84
105
|
def self.deprecator
|
|
85
|
-
@deprecator ||= ActiveSupport::Deprecation.new(
|
|
106
|
+
@deprecator ||= ActiveSupport::Deprecation.new("#{Gem::Version.new(VERSION).segments.first + 1}.0", 'Grape')
|
|
86
107
|
end
|
|
87
108
|
end
|
|
88
109
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: grape
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Bleigh
|
|
@@ -156,6 +156,7 @@ files:
|
|
|
156
156
|
- lib/grape/exceptions/missing_vendor_option.rb
|
|
157
157
|
- lib/grape/exceptions/request_error.rb
|
|
158
158
|
- lib/grape/exceptions/unknown_auth_strategy.rb
|
|
159
|
+
- lib/grape/exceptions/unknown_error_formatter.rb
|
|
159
160
|
- lib/grape/exceptions/unknown_parameter.rb
|
|
160
161
|
- lib/grape/exceptions/unknown_params_builder.rb
|
|
161
162
|
- lib/grape/exceptions/unknown_validator.rb
|
|
@@ -176,7 +177,6 @@ files:
|
|
|
176
177
|
- lib/grape/middleware/auth/strategies.rb
|
|
177
178
|
- lib/grape/middleware/auth/strategy_info.rb
|
|
178
179
|
- lib/grape/middleware/base.rb
|
|
179
|
-
- lib/grape/middleware/deprecated_options_hash_access.rb
|
|
180
180
|
- lib/grape/middleware/error.rb
|
|
181
181
|
- lib/grape/middleware/filter.rb
|
|
182
182
|
- lib/grape/middleware/formatter.rb
|
|
@@ -200,6 +200,7 @@ files:
|
|
|
200
200
|
- lib/grape/parser/json.rb
|
|
201
201
|
- lib/grape/parser/xml.rb
|
|
202
202
|
- lib/grape/path.rb
|
|
203
|
+
- lib/grape/precompiled_json.rb
|
|
203
204
|
- lib/grape/presenters/presenter.rb
|
|
204
205
|
- lib/grape/railtie.rb
|
|
205
206
|
- lib/grape/request.rb
|
|
@@ -208,19 +209,19 @@ files:
|
|
|
208
209
|
- lib/grape/router/greedy_route.rb
|
|
209
210
|
- lib/grape/router/mustermann_pattern.rb
|
|
210
211
|
- lib/grape/router/pattern.rb
|
|
212
|
+
- lib/grape/router/pattern/path.rb
|
|
211
213
|
- lib/grape/router/route.rb
|
|
212
214
|
- lib/grape/serve_stream/file_body.rb
|
|
213
215
|
- lib/grape/serve_stream/sendfile_response.rb
|
|
214
216
|
- lib/grape/serve_stream/stream_response.rb
|
|
215
217
|
- lib/grape/testing.rb
|
|
216
218
|
- lib/grape/util/api_description.rb
|
|
217
|
-
- lib/grape/util/base_inheritable.rb
|
|
218
219
|
- lib/grape/util/cache.rb
|
|
219
220
|
- lib/grape/util/deep_freeze.rb
|
|
220
221
|
- lib/grape/util/endpoint_configuration.rb
|
|
222
|
+
- lib/grape/util/freeze_on_new.rb
|
|
221
223
|
- lib/grape/util/header.rb
|
|
222
224
|
- lib/grape/util/inheritable_setting.rb
|
|
223
|
-
- lib/grape/util/inheritable_values.rb
|
|
224
225
|
- lib/grape/util/lazy/base.rb
|
|
225
226
|
- lib/grape/util/lazy/block.rb
|
|
226
227
|
- lib/grape/util/lazy/value.rb
|
|
@@ -230,7 +231,7 @@ files:
|
|
|
230
231
|
- lib/grape/util/media_type.rb
|
|
231
232
|
- lib/grape/util/path_normalizer.rb
|
|
232
233
|
- lib/grape/util/registry.rb
|
|
233
|
-
- lib/grape/util/
|
|
234
|
+
- lib/grape/util/shadowed_rescue_handlers.rb
|
|
234
235
|
- lib/grape/util/stackable_values.rb
|
|
235
236
|
- lib/grape/util/translation.rb
|
|
236
237
|
- lib/grape/validations.rb
|
|
@@ -282,9 +283,9 @@ licenses:
|
|
|
282
283
|
- MIT
|
|
283
284
|
metadata:
|
|
284
285
|
bug_tracker_uri: https://github.com/ruby-grape/grape/issues
|
|
285
|
-
changelog_uri: https://github.com/ruby-grape/grape/blob/
|
|
286
|
-
documentation_uri: https://www.rubydoc.info/gems/grape/
|
|
287
|
-
source_code_uri: https://github.com/ruby-grape/grape/tree/
|
|
286
|
+
changelog_uri: https://github.com/ruby-grape/grape/blob/v4.0.0/CHANGELOG.md
|
|
287
|
+
documentation_uri: https://www.rubydoc.info/gems/grape/4.0.0
|
|
288
|
+
source_code_uri: https://github.com/ruby-grape/grape/tree/v4.0.0
|
|
288
289
|
rubygems_mfa_required: 'true'
|
|
289
290
|
rdoc_options: []
|
|
290
291
|
require_paths:
|
|
@@ -300,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
300
301
|
- !ruby/object:Gem::Version
|
|
301
302
|
version: '0'
|
|
302
303
|
requirements: []
|
|
303
|
-
rubygems_version: 4.0.
|
|
304
|
+
rubygems_version: 4.0.16
|
|
304
305
|
specification_version: 4
|
|
305
306
|
summary: A simple Ruby framework for building REST-like APIs.
|
|
306
307
|
test_files: []
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Middleware
|
|
5
|
-
# Mixin for per-middleware +Options+ +Data+ classes that need to keep
|
|
6
|
-
# accepting legacy +data[:key]+ Hash-style access while nudging callers
|
|
7
|
-
# toward the named accessor. Emits a +Grape.deprecator+ warning then
|
|
8
|
-
# forwards to +public_send(key)+.
|
|
9
|
-
module DeprecatedOptionsHashAccess
|
|
10
|
-
def [](key)
|
|
11
|
-
Grape.deprecator.warn(
|
|
12
|
-
"`#{self.class.name}#[]` is deprecated. " \
|
|
13
|
-
"Use the named accessor `#{key}` instead."
|
|
14
|
-
)
|
|
15
|
-
public_send(key) if members.include?(key)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Util
|
|
5
|
-
# Base for classes which need to operate with own values kept
|
|
6
|
-
# in the hash and inherited values kept in a Hash-like object.
|
|
7
|
-
#
|
|
8
|
-
# +@new_values+ is lazily allocated on first write so settings layers
|
|
9
|
-
# that only inherit (never override) don't carry an empty Hash each.
|
|
10
|
-
class BaseInheritable
|
|
11
|
-
attr_accessor :inherited_values, :new_values
|
|
12
|
-
|
|
13
|
-
# @param inherited_values [Object] An object implementing an interface
|
|
14
|
-
# of the Hash class.
|
|
15
|
-
def initialize(inherited_values = nil)
|
|
16
|
-
@inherited_values = inherited_values || {}
|
|
17
|
-
# @new_values stays nil until the first write.
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def delete(*keys)
|
|
21
|
-
return [] unless @new_values
|
|
22
|
-
|
|
23
|
-
keys.map { |key| @new_values.delete(key) }
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def initialize_copy(other)
|
|
27
|
-
super
|
|
28
|
-
@inherited_values = other.inherited_values
|
|
29
|
-
@new_values = other.new_values&.dup
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def keys
|
|
33
|
-
return @inherited_values.keys if @new_values.nil? || @new_values.empty?
|
|
34
|
-
|
|
35
|
-
(@inherited_values.keys + @new_values.keys).uniq
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def key?(name)
|
|
39
|
-
@inherited_values.key?(name) || @new_values&.key?(name) || false
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Util
|
|
5
|
-
class InheritableValues < BaseInheritable
|
|
6
|
-
def [](name)
|
|
7
|
-
return @inherited_values[name] unless @new_values
|
|
8
|
-
|
|
9
|
-
@new_values.fetch(name) { @inherited_values[name] }
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def []=(name, value)
|
|
13
|
-
(@new_values ||= {})[name] = value
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def merge(new_hash)
|
|
17
|
-
values.merge!(new_hash)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def to_hash
|
|
21
|
-
values
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
protected
|
|
25
|
-
|
|
26
|
-
def values
|
|
27
|
-
return @inherited_values.merge(@new_values) if @new_values && !@new_values.empty?
|
|
28
|
-
|
|
29
|
-
@inherited_values.is_a?(Hash) ? @inherited_values.dup : @inherited_values.to_hash
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Util
|
|
5
|
-
class ReverseStackableValues < StackableValues
|
|
6
|
-
protected
|
|
7
|
-
|
|
8
|
-
def concat_values(inherited_value, new_value)
|
|
9
|
-
return inherited_value unless new_value
|
|
10
|
-
|
|
11
|
-
new_value + inherited_value
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|