-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
inheritable_setting.rb
102 lines (86 loc) · 3.48 KB
/
inheritable_setting.rb
1
2
3
4
5
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# frozen_string_literal: true
module Grape
module Util
# A branchable, inheritable settings object which can store both stackable
# and inheritable values (see InheritableValues and StackableValues).
class InheritableSetting
attr_accessor :route, :api_class, :namespace
attr_accessor :namespace_inheritable, :namespace_stackable, :namespace_reverse_stackable
attr_accessor :parent, :point_in_time_copies
# Retrieve global settings.
def self.global
@global ||= {}
end
# Clear all global settings.
# @api private
# @note only for testing
def self.reset_global!
@global = {}
end
# Instantiate a new settings instance, with blank values. The fresh
# instance can then be set to inherit from an existing instance (see
# #inherit_from).
def initialize
self.route = {}
self.api_class = {}
self.namespace = InheritableValues.new # only inheritable from a parent when
# used with a mount, or should every API::Class be a separate namespace by default?
self.namespace_inheritable = InheritableValues.new
self.namespace_stackable = StackableValues.new
self.namespace_reverse_stackable = ReverseStackableValues.new
self.point_in_time_copies = []
self.parent = nil
end
# Return the class-level global properties.
def global
self.class.global
end
# Set our inherited values to the given parent's current values. Also,
# update the inherited values on any settings instances which were forked
# from us.
# @param parent [InheritableSetting]
def inherit_from(parent)
return if parent.nil?
self.parent = parent
namespace_inheritable.inherited_values = parent.namespace_inheritable
namespace_stackable.inherited_values = parent.namespace_stackable
namespace_reverse_stackable.inherited_values = parent.namespace_reverse_stackable
self.route = parent.route.merge(route)
point_in_time_copies.map { |cloned_one| cloned_one.inherit_from parent }
end
# Create a point-in-time copy of this settings instance, with clones of
# all our values. Note that, should this instance's parent be set or
# changed via #inherit_from, it will copy that inheritence to any copies
# which were made.
def point_in_time_copy
self.class.new.tap do |new_setting|
point_in_time_copies << new_setting
new_setting.point_in_time_copies = []
new_setting.namespace = namespace.clone
new_setting.namespace_inheritable = namespace_inheritable.clone
new_setting.namespace_stackable = namespace_stackable.clone
new_setting.namespace_reverse_stackable = namespace_reverse_stackable.clone
new_setting.route = route.clone
new_setting.api_class = api_class
new_setting.inherit_from(parent)
end
end
# Resets the instance store of per-route settings.
# @api private
def route_end
@route = {}
end
# Return a serializable hash of our values.
def to_hash
{
global: global.clone,
route: route.clone,
namespace: namespace.to_hash,
namespace_inheritable: namespace_inheritable.to_hash,
namespace_stackable: namespace_stackable.to_hash,
namespace_reverse_stackable: namespace_reverse_stackable.to_hash
}
end
end
end
end