grape 0.9.0 → 0.10.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.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -66
- data/.rubocop_todo.yml +78 -17
- data/.travis.yml +7 -3
- data/Appraisals +7 -0
- data/CHANGELOG.md +24 -0
- data/CONTRIBUTING.md +7 -0
- data/Gemfile +1 -7
- data/Guardfile +1 -1
- data/README.md +560 -94
- data/RELEASING.md +1 -1
- data/Rakefile +10 -11
- data/UPGRADING.md +211 -3
- data/gemfiles/rails_3.gemfile +14 -0
- data/gemfiles/rails_4.gemfile +14 -0
- data/grape.gemspec +10 -9
- data/lib/backports/active_support/deep_dup.rb +49 -0
- data/lib/backports/active_support/duplicable.rb +88 -0
- data/lib/grape.rb +29 -2
- data/lib/grape/api.rb +59 -65
- data/lib/grape/dsl/api.rb +19 -0
- data/lib/grape/dsl/callbacks.rb +6 -4
- data/lib/grape/dsl/configuration.rb +49 -5
- data/lib/grape/dsl/helpers.rb +7 -8
- data/lib/grape/dsl/inside_route.rb +22 -10
- data/lib/grape/dsl/middleware.rb +5 -5
- data/lib/grape/dsl/parameters.rb +6 -2
- data/lib/grape/dsl/request_response.rb +23 -20
- data/lib/grape/dsl/routing.rb +52 -49
- data/lib/grape/dsl/settings.rb +110 -0
- data/lib/grape/dsl/validations.rb +14 -6
- data/lib/grape/endpoint.rb +104 -88
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -1
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/missing_option.rb +1 -1
- data/lib/grape/exceptions/missing_vendor_option.rb +1 -1
- data/lib/grape/exceptions/unknown_options.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/validation.rb +1 -1
- data/lib/grape/exceptions/validation_errors.rb +2 -2
- data/lib/grape/formatter/serializable_hash.rb +1 -1
- data/lib/grape/formatter/xml.rb +1 -1
- data/lib/grape/locale/en.yml +2 -0
- data/lib/grape/middleware/auth/dsl.rb +26 -21
- data/lib/grape/middleware/auth/strategies.rb +1 -1
- data/lib/grape/middleware/auth/strategy_info.rb +0 -2
- data/lib/grape/middleware/base.rb +2 -2
- data/lib/grape/middleware/error.rb +1 -1
- data/lib/grape/middleware/formatter.rb +5 -5
- data/lib/grape/middleware/versioner.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +3 -3
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/namespace.rb +1 -1
- data/lib/grape/path.rb +9 -3
- data/lib/grape/util/content_types.rb +16 -8
- data/lib/grape/util/inheritable_setting.rb +74 -0
- data/lib/grape/util/inheritable_values.rb +51 -0
- data/lib/grape/util/stackable_values.rb +52 -0
- data/lib/grape/util/strict_hash_configuration.rb +106 -0
- data/lib/grape/validations.rb +0 -220
- data/lib/grape/validations/attributes_iterator.rb +21 -0
- data/lib/grape/validations/params_scope.rb +176 -0
- data/lib/grape/validations/validators/all_or_none.rb +20 -0
- data/lib/grape/validations/validators/allow_blank.rb +30 -0
- data/lib/grape/validations/validators/at_least_one_of.rb +20 -0
- data/lib/grape/validations/validators/base.rb +37 -0
- data/lib/grape/validations/{coerce.rb → validators/coerce.rb} +3 -3
- data/lib/grape/validations/{default.rb → validators/default.rb} +1 -1
- data/lib/grape/validations/validators/exactly_one_of.rb +20 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +26 -0
- data/lib/grape/validations/validators/mutual_exclusion.rb +25 -0
- data/lib/grape/validations/{presence.rb → validators/presence.rb} +2 -2
- data/lib/grape/validations/validators/regexp.rb +12 -0
- data/lib/grape/validations/validators/values.rb +26 -0
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +522 -343
- data/spec/grape/dsl/callbacks_spec.rb +4 -4
- data/spec/grape/dsl/configuration_spec.rb +48 -9
- data/spec/grape/dsl/helpers_spec.rb +6 -13
- data/spec/grape/dsl/inside_route_spec.rb +43 -4
- data/spec/grape/dsl/middleware_spec.rb +1 -10
- data/spec/grape/dsl/parameters_spec.rb +8 -1
- data/spec/grape/dsl/request_response_spec.rb +16 -22
- data/spec/grape/dsl/routing_spec.rb +21 -5
- data/spec/grape/dsl/settings_spec.rb +219 -0
- data/spec/grape/dsl/validations_spec.rb +8 -11
- data/spec/grape/endpoint_spec.rb +115 -86
- data/spec/grape/entity_spec.rb +33 -33
- data/spec/grape/exceptions/invalid_formatter_spec.rb +3 -5
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +4 -6
- data/spec/grape/exceptions/missing_mime_type_spec.rb +5 -6
- data/spec/grape/exceptions/missing_option_spec.rb +3 -5
- data/spec/grape/exceptions/unknown_options_spec.rb +3 -5
- data/spec/grape/exceptions/unknown_validator_spec.rb +3 -5
- data/spec/grape/exceptions/validation_errors_spec.rb +5 -5
- data/spec/grape/loading_spec.rb +44 -0
- data/spec/grape/middleware/auth/base_spec.rb +0 -4
- data/spec/grape/middleware/auth/dsl_spec.rb +2 -4
- data/spec/grape/middleware/auth/strategies_spec.rb +5 -6
- data/spec/grape/middleware/exception_spec.rb +8 -10
- data/spec/grape/middleware/formatter_spec.rb +13 -15
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +10 -10
- data/spec/grape/middleware/versioner/header_spec.rb +25 -25
- data/spec/grape/middleware/versioner/param_spec.rb +15 -17
- data/spec/grape/middleware/versioner/path_spec.rb +1 -2
- data/spec/grape/middleware/versioner_spec.rb +0 -1
- data/spec/grape/path_spec.rb +66 -45
- data/spec/grape/util/inheritable_setting_spec.rb +217 -0
- data/spec/grape/util/inheritable_values_spec.rb +63 -0
- data/spec/grape/util/stackable_values_spec.rb +115 -0
- data/spec/grape/util/strict_hash_configuration_spec.rb +38 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +4 -0
- data/spec/grape/validations/params_scope_spec.rb +57 -0
- data/spec/grape/validations/validators/all_or_none_spec.rb +60 -0
- data/spec/grape/validations/validators/allow_blank_spec.rb +170 -0
- data/spec/grape/validations/{at_least_one_of_spec.rb → validators/at_least_one_of_spec.rb} +7 -3
- data/spec/grape/validations/{coerce_spec.rb → validators/coerce_spec.rb} +8 -11
- data/spec/grape/validations/{default_spec.rb → validators/default_spec.rb} +7 -9
- data/spec/grape/validations/{exactly_one_of_spec.rb → validators/exactly_one_of_spec.rb} +15 -11
- data/spec/grape/validations/{mutual_exclusion_spec.rb → validators/mutual_exclusion_spec.rb} +11 -9
- data/spec/grape/validations/{presence_spec.rb → validators/presence_spec.rb} +30 -30
- data/spec/grape/validations/{regexp_spec.rb → validators/regexp_spec.rb} +2 -4
- data/spec/grape/validations/{values_spec.rb → validators/values_spec.rb} +95 -23
- data/spec/grape/validations/{zh-CN.yml → validators/zh-CN.yml} +0 -0
- data/spec/grape/validations_spec.rb +335 -70
- data/spec/shared/versioning_examples.rb +7 -8
- data/spec/spec_helper.rb +2 -0
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- data/spec/support/content_type_helpers.rb +1 -1
- data/spec/support/versioned_helpers.rb +3 -3
- metadata +80 -33
- data/lib/grape/util/deep_merge.rb +0 -23
- data/lib/grape/util/hash_stack.rb +0 -120
- data/lib/grape/validations/at_least_one_of.rb +0 -25
- data/lib/grape/validations/exactly_one_of.rb +0 -26
- data/lib/grape/validations/mutual_exclusion.rb +0 -25
- data/lib/grape/validations/regexp.rb +0 -12
- data/lib/grape/validations/values.rb +0 -23
- data/spec/grape/util/hash_stack_spec.rb +0 -132
@@ -3,7 +3,7 @@ module Grape
|
|
3
3
|
module Exceptions
|
4
4
|
class UnknownValidator < Base
|
5
5
|
def initialize(validator_type)
|
6
|
-
super(message: compose_message(
|
6
|
+
super(message: compose_message('unknown_validator', validator_type: validator_type))
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -6,7 +6,7 @@ module Grape
|
|
6
6
|
attr_accessor :params
|
7
7
|
|
8
8
|
def initialize(args = {})
|
9
|
-
|
9
|
+
fail 'Params are missing:' unless args.key? :params
|
10
10
|
@params = args[:params]
|
11
11
|
args[:message] = translate_message(args[:message_key]) if args.key? :message_key
|
12
12
|
super
|
@@ -45,8 +45,8 @@ module Grape
|
|
45
45
|
|
46
46
|
def full_message(attributes, error)
|
47
47
|
I18n.t(
|
48
|
-
|
49
|
-
default:
|
48
|
+
'grape.errors.format'.to_sym,
|
49
|
+
default: '%{attributes} %{message}',
|
50
50
|
attributes: attributes.count == 1 ? translate_attribute(attributes.first) : translate_attributes(attributes),
|
51
51
|
message: error.message
|
52
52
|
)
|
@@ -19,7 +19,7 @@ module Grape
|
|
19
19
|
if object.respond_to? :serializable_hash
|
20
20
|
object.serializable_hash
|
21
21
|
elsif object.kind_of?(Array) && !object.map { |o| o.respond_to? :serializable_hash }.include?(false)
|
22
|
-
object.map
|
22
|
+
object.map(&:serializable_hash)
|
23
23
|
elsif object.kind_of?(Hash)
|
24
24
|
object.inject({}) do |h, (k, v)|
|
25
25
|
h[k] = serialize(v)
|
data/lib/grape/formatter/xml.rb
CHANGED
data/lib/grape/locale/en.yml
CHANGED
@@ -6,6 +6,7 @@ en:
|
|
6
6
|
coerce: 'is invalid'
|
7
7
|
presence: 'is missing'
|
8
8
|
regexp: 'is invalid'
|
9
|
+
blank: 'is empty'
|
9
10
|
values: 'does not have a valid value'
|
10
11
|
missing_vendor_option:
|
11
12
|
problem: 'missing :vendor option.'
|
@@ -31,4 +32,5 @@ en:
|
|
31
32
|
mutual_exclusion: 'are mutually exclusive'
|
32
33
|
at_least_one: 'are missing, at least one parameter must be provided'
|
33
34
|
exactly_one: 'are missing, exactly one parameter must be provided'
|
35
|
+
all_or_none: 'provide all or none of parameters'
|
34
36
|
|
@@ -1,33 +1,38 @@
|
|
1
1
|
require 'rack/auth/basic'
|
2
|
+
require 'active_support/concern'
|
2
3
|
|
3
4
|
module Grape
|
4
5
|
module Middleware
|
5
6
|
module Auth
|
6
7
|
module DSL
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Add an authentication type to the API. Currently
|
12
|
+
# only `:http_basic`, `:http_digest` are supported.
|
13
|
+
def auth(type = nil, options = {}, &block)
|
14
|
+
if type
|
15
|
+
namespace_inheritable(:auth, { type: type.to_sym, proc: block }.merge(options))
|
16
|
+
use Grape::Middleware::Auth::Base, namespace_inheritable(:auth)
|
17
|
+
else
|
18
|
+
namespace_inheritable(:auth)
|
19
|
+
end
|
15
20
|
end
|
16
|
-
end
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
# Add HTTP Basic authorization to the API.
|
23
|
+
#
|
24
|
+
# @param [Hash] options A hash of options.
|
25
|
+
# @option options [String] :realm "API Authorization" The HTTP Basic realm.
|
26
|
+
def http_basic(options = {}, &block)
|
27
|
+
options[:realm] ||= 'API Authorization'
|
28
|
+
auth :http_basic, options, &block
|
29
|
+
end
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
def http_digest(options = {}, &block)
|
32
|
+
options[:realm] ||= 'API Authorization'
|
33
|
+
options[:opaque] ||= 'secret'
|
34
|
+
auth :http_digest, options, &block
|
35
|
+
end
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -10,7 +10,7 @@ module Grape
|
|
10
10
|
|
11
11
|
def auth_strategies
|
12
12
|
@auth_strategies ||= {
|
13
|
-
http_basic: StrategyInfo.new(Rack::Auth::Basic, ->(settings) {[settings[:realm]] }),
|
13
|
+
http_basic: StrategyInfo.new(Rack::Auth::Basic, ->(settings) { [settings[:realm]] }),
|
14
14
|
http_digest: StrategyInfo.new(Rack::Auth::Digest::MD5, ->(settings) { [settings[:realm], settings[:opaque]] })
|
15
15
|
}
|
16
16
|
end
|
@@ -2,13 +2,11 @@ module Grape
|
|
2
2
|
module Middleware
|
3
3
|
module Auth
|
4
4
|
StrategyInfo = Struct.new(:auth_class, :settings_fetcher) do
|
5
|
-
|
6
5
|
def create(app, options, &block)
|
7
6
|
strategy_args = settings_fetcher.call(options)
|
8
7
|
|
9
8
|
auth_class.new(app, *strategy_args, &block)
|
10
9
|
end
|
11
|
-
|
12
10
|
end
|
13
11
|
end
|
14
12
|
end
|
@@ -53,9 +53,9 @@ module Grape
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def mime_types
|
56
|
-
content_types.each_with_object({})
|
56
|
+
content_types.each_with_object({}) do |(k, v), types_without_params|
|
57
57
|
types_without_params[k] = v.split(';').first
|
58
|
-
|
58
|
+
end.invert
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -26,7 +26,7 @@ module Grape
|
|
26
26
|
def after
|
27
27
|
status, headers, bodies = *@app_response
|
28
28
|
# allow content-type to be explicitly overwritten
|
29
|
-
api_format = mime_types[headers[
|
29
|
+
api_format = mime_types[headers['Content-Type']] || env['api.format']
|
30
30
|
formatter = Grape::Formatter::Base.formatter_for api_format, options
|
31
31
|
begin
|
32
32
|
bodymap = bodies.collect do |body|
|
@@ -48,9 +48,9 @@ module Grape
|
|
48
48
|
# store read input in env['api.request.input']
|
49
49
|
def read_body_input
|
50
50
|
if (request.post? || request.put? || request.patch? || request.delete?) &&
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
(!request.form_data? || !request.media_type) &&
|
52
|
+
(!request.parseable_data?) &&
|
53
|
+
(request.content_length.to_i > 0 || request.env['HTTP_TRANSFER_ENCODING'] == 'chunked')
|
54
54
|
|
55
55
|
if (input = env['rack.input'])
|
56
56
|
input.rewind
|
@@ -113,7 +113,7 @@ module Grape
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def format_from_params
|
116
|
-
fmt = Rack::Utils.parse_nested_query(env['QUERY_STRING'])[
|
116
|
+
fmt = Rack::Utils.parse_nested_query(env['QUERY_STRING'])['format']
|
117
117
|
# avoid symbol memory leak on an unknown format
|
118
118
|
return fmt.to_sym if content_type_for(fmt)
|
119
119
|
fmt
|
@@ -52,9 +52,9 @@ module Grape
|
|
52
52
|
env['api.subtype'] = subtype
|
53
53
|
|
54
54
|
if /\Avnd\.([a-z0-9*.]+)(?:-([a-z0-9*\-.]+))?(?:\+([a-z0-9*\-.+]+))?\z/ =~ subtype
|
55
|
-
env['api.vendor'] =
|
56
|
-
env['api.version'] =
|
57
|
-
env['api.format'] =
|
55
|
+
env['api.vendor'] = Regexp.last_match[1]
|
56
|
+
env['api.version'] = Regexp.last_match[2]
|
57
|
+
env['api.format'] = Regexp.last_match[3] # weird that Grape::Middleware::Formatter also does this
|
58
58
|
end
|
59
59
|
# If none of the available content types are acceptable:
|
60
60
|
elsif strict?
|
@@ -21,7 +21,7 @@ module Grape
|
|
21
21
|
class Param < Base
|
22
22
|
def default_options
|
23
23
|
{
|
24
|
-
parameter:
|
24
|
+
parameter: 'apiver'
|
25
25
|
}
|
26
26
|
end
|
27
27
|
|
@@ -30,7 +30,7 @@ module Grape
|
|
30
30
|
potential_version = Rack::Utils.parse_nested_query(env['QUERY_STRING'])[paramkey]
|
31
31
|
unless potential_version.nil?
|
32
32
|
if options[:versions] && !options[:versions].find { |v| v.to_s == potential_version }
|
33
|
-
throw :error, status: 404, message:
|
33
|
+
throw :error, status: 404, message: '404 API Version Not Found', headers: { 'X-Cascade' => 'pass' }
|
34
34
|
end
|
35
35
|
env['api.version'] = potential_version
|
36
36
|
env['rack.request.query_hash'].delete(paramkey) if env.key? 'rack.request.query_hash'
|
@@ -35,7 +35,7 @@ module Grape
|
|
35
35
|
potential_version = pieces[1]
|
36
36
|
if potential_version =~ options[:pattern]
|
37
37
|
if options[:versions] && !options[:versions].find { |v| v.to_s == potential_version }
|
38
|
-
throw :error, status: 404, message:
|
38
|
+
throw :error, status: 404, message: '404 API Version Not Found'
|
39
39
|
end
|
40
40
|
env['api.version'] = potential_version
|
41
41
|
end
|
data/lib/grape/namespace.rb
CHANGED
data/lib/grape/path.rb
CHANGED
@@ -13,13 +13,17 @@ module Grape
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def mount_path
|
16
|
-
|
16
|
+
settings[:mount_path]
|
17
17
|
end
|
18
18
|
|
19
19
|
def root_prefix
|
20
20
|
split_setting(:root_prefix, '/')
|
21
21
|
end
|
22
22
|
|
23
|
+
def uses_specific_format?
|
24
|
+
!!(settings[:format] && settings[:content_types].size == 1)
|
25
|
+
end
|
26
|
+
|
23
27
|
def uses_path_versioning?
|
24
28
|
!!(settings[:version] && settings[:version_options][:using] == :path)
|
25
29
|
end
|
@@ -33,7 +37,9 @@ module Grape
|
|
33
37
|
end
|
34
38
|
|
35
39
|
def suffix
|
36
|
-
if
|
40
|
+
if uses_specific_format?
|
41
|
+
''
|
42
|
+
elsif !uses_path_versioning? || (has_namespace? || has_path?)
|
37
43
|
'(.:format)'
|
38
44
|
else
|
39
45
|
'(/.:format)'
|
@@ -64,7 +70,7 @@ module Grape
|
|
64
70
|
|
65
71
|
def split_setting(key, delimiter)
|
66
72
|
return if settings[key].nil?
|
67
|
-
settings[key].to_s.split(
|
73
|
+
settings[key].to_s.split('/')
|
68
74
|
end
|
69
75
|
end
|
70
76
|
end
|
@@ -2,17 +2,25 @@ module Grape
|
|
2
2
|
module ContentTypes
|
3
3
|
# Content types are listed in order of preference.
|
4
4
|
CONTENT_TYPES = ActiveSupport::OrderedHash[
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
:rss, 'application/rss+xml',
|
11
|
-
:txt, 'text/plain',
|
5
|
+
:xml, 'application/xml',
|
6
|
+
:serializable_hash, 'application/json',
|
7
|
+
:json, 'application/json',
|
8
|
+
:binary, 'application/octet-stream',
|
9
|
+
:txt, 'text/plain'
|
12
10
|
]
|
13
11
|
|
12
|
+
def self.content_types_for_settings(settings)
|
13
|
+
return nil if settings.nil? || settings.blank?
|
14
|
+
|
15
|
+
settings.each_with_object(ActiveSupport::OrderedHash.new) { |value, result| result.merge!(value) }
|
16
|
+
end
|
17
|
+
|
14
18
|
def self.content_types_for(from_settings)
|
15
|
-
from_settings
|
19
|
+
if from_settings.present?
|
20
|
+
from_settings
|
21
|
+
else
|
22
|
+
Grape::ContentTypes::CONTENT_TYPES
|
23
|
+
end
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Grape
|
2
|
+
module Util
|
3
|
+
class InheritableSetting
|
4
|
+
attr_accessor :route, :api_class, :namespace, :namespace_inheritable, :namespace_stackable
|
5
|
+
attr_accessor :parent, :point_in_time_copies
|
6
|
+
|
7
|
+
def self.global
|
8
|
+
@global ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.reset_global! # only for testing
|
12
|
+
@global = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
self.route = {}
|
17
|
+
self.api_class = {}
|
18
|
+
self.namespace = InheritableValues.new # only inheritable from a parent when
|
19
|
+
# used with a mount, or should every API::Class be a seperate namespace by default?
|
20
|
+
self.namespace_inheritable = InheritableValues.new
|
21
|
+
self.namespace_stackable = StackableValues.new
|
22
|
+
|
23
|
+
self.point_in_time_copies = []
|
24
|
+
|
25
|
+
self.parent = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def global
|
29
|
+
self.class.global
|
30
|
+
end
|
31
|
+
|
32
|
+
def inherit_from(parent)
|
33
|
+
return if parent.nil?
|
34
|
+
|
35
|
+
self.parent = parent
|
36
|
+
|
37
|
+
namespace_inheritable.inherited_values = parent.namespace_inheritable
|
38
|
+
namespace_stackable.inherited_values = parent.namespace_stackable
|
39
|
+
self.route = parent.route.merge(route)
|
40
|
+
|
41
|
+
point_in_time_copies.map { |cloned_one| cloned_one.inherit_from parent }
|
42
|
+
end
|
43
|
+
|
44
|
+
def point_in_time_copy
|
45
|
+
self.class.new.tap do |new_setting|
|
46
|
+
point_in_time_copies << new_setting
|
47
|
+
new_setting.point_in_time_copies = []
|
48
|
+
|
49
|
+
new_setting.namespace = namespace.clone
|
50
|
+
new_setting.namespace_inheritable = namespace_inheritable.clone
|
51
|
+
new_setting.namespace_stackable = namespace_stackable.clone
|
52
|
+
new_setting.route = route.clone
|
53
|
+
new_setting.api_class = api_class
|
54
|
+
|
55
|
+
new_setting.inherit_from(parent)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def route_end
|
60
|
+
@route = {}
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_hash
|
64
|
+
{
|
65
|
+
global: global.clone,
|
66
|
+
route: route.clone,
|
67
|
+
namespace: namespace.to_hash,
|
68
|
+
namespace_inheritable: namespace_inheritable.to_hash,
|
69
|
+
namespace_stackable: namespace_stackable.to_hash
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Grape
|
2
|
+
module Util
|
3
|
+
class InheritableValues
|
4
|
+
attr_accessor :inherited_values
|
5
|
+
attr_accessor :new_values
|
6
|
+
|
7
|
+
def initialize(inherited_values = {})
|
8
|
+
self.inherited_values = inherited_values
|
9
|
+
self.new_values = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](name)
|
13
|
+
values[name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(name, value)
|
17
|
+
new_values[name] = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete(key)
|
21
|
+
new_values.delete key
|
22
|
+
end
|
23
|
+
|
24
|
+
def merge(new_hash)
|
25
|
+
values.merge(new_hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
def keys
|
29
|
+
(new_values.keys + inherited_values.keys).sort.uniq
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_hash
|
33
|
+
values.clone
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize_copy(other)
|
37
|
+
super
|
38
|
+
self.inherited_values = other.inherited_values
|
39
|
+
self.new_values = other.new_values.deep_dup
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_writer :new_values
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def values
|
47
|
+
@inherited_values.merge(@new_values)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|