-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathlazy_value.rb
95 lines (83 loc) · 2.19 KB
/
lazy_value.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
module Grape
module Util
class LazyValue
attr_reader :access_keys
def initialize(value, access_keys = [])
@value = value
@access_keys = access_keys
end
def evaluate_from(configuration)
matching_lazy_value = configuration.fetch(@access_keys)
matching_lazy_value.evaluate
end
def evaluate
@value
end
def lazy?
true
end
def reached_by(parent_access_keys, access_key)
@access_keys = parent_access_keys + [access_key]
self
end
def to_s
evaluate.to_s
end
end
class LazyValueEnumerable < LazyValue
def [](key)
if @value_hash[key].nil?
LazyValue.new(nil).reached_by(access_keys, key)
else
@value_hash[key].reached_by(access_keys, key)
end
end
def fetch(access_keys)
fetched_keys = access_keys.dup
value = self[fetched_keys.shift]
fetched_keys.any? ? value.fetch(fetched_keys) : value
end
def []=(key, value)
@value_hash[key] = if value.is_a?(Hash)
LazyValueHash.new(value)
elsif value.is_a?(Array)
LazyValueArray.new(value)
else
LazyValue.new(value)
end
end
end
class LazyValueArray < LazyValueEnumerable
def initialize(array)
super
@value_hash = []
array.each_with_index do |value, index|
self[index] = value
end
end
def evaluate
evaluated = []
@value_hash.each_with_index do |value, index|
evaluated[index] = value.evaluate
end
evaluated
end
end
class LazyValueHash < LazyValueEnumerable
def initialize(hash)
super
@value_hash = {}.with_indifferent_access
hash.each do |key, value|
self[key] = value
end
end
def evaluate
evaluated = {}.with_indifferent_access
@value_hash.each do |key, value|
evaluated[key] = value.evaluate
end
evaluated
end
end
end
end