lazy_lazer 0.7.0 → 0.7.1
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/README.md +19 -3
- data/lib/lazy_lazer.rb +12 -59
- data/lib/lazy_lazer/internal_model.rb +49 -23
- data/lib/lazy_lazer/key_metadata.rb +2 -2
- data/lib/lazy_lazer/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02623a4fd292219e52a37ab7ff9403f19a04341f
|
4
|
+
data.tar.gz: '0609a64cf39456530d98a0d317055256cf004317'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 315a2b347aca6b3c668f167cd086ede566861f9c1c5a5ebf6dad5ddf3d41fb7409007af3e8f812d7f75aa94487d35940bef90a076d589d0c3bcf4bddfe0fc3b0
|
7
|
+
data.tar.gz: 12020aba963d98ab204e3809a60327d7d447adf014a4bfada76aa3ff04745ddd1db3be95bee301ba6339a120d6088d9bb1aaa56cb880e4c1ef88a9d18270c17f
|
data/README.md
CHANGED
@@ -8,22 +8,34 @@ require 'lazy_lazer'
|
|
8
8
|
class User
|
9
9
|
include LazyLazer
|
10
10
|
|
11
|
-
property :
|
11
|
+
property :name, :required
|
12
12
|
property :email, default: 'unknown@example.com'
|
13
13
|
property :created_at, from: :creation_time_utc, with: ->(t) { Time.at(t) }
|
14
14
|
property :age, with: :to_i
|
15
15
|
property :twitter_handle, :nil
|
16
16
|
property :favorite_ice_cream
|
17
17
|
|
18
|
+
def try_another_flavor!
|
19
|
+
if exists_locally?(:favorite_ice_cream)
|
20
|
+
puts "#{name} currently likes #{favorite_ice_cream}."
|
21
|
+
else
|
22
|
+
puts "#{name} doesn't have a favorite ice cream flavor yet."
|
23
|
+
end
|
24
|
+
invalidate(:favorite_ice_cream)
|
25
|
+
puts "#{name} just tried #{favorite_ice_cream}. They love it!"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
18
30
|
def lazer_reload
|
19
31
|
fully_loaded! # mark model as fully updated
|
20
32
|
{ favorite_ice_cream: %w[vanilla strawberry chocolate].sample }
|
21
33
|
end
|
22
34
|
end
|
23
35
|
|
24
|
-
user = User.new(
|
36
|
+
user = User.new(name: 'Blinky', creation_time_utc: 1500000000, age: '21')
|
25
37
|
|
26
|
-
user.
|
38
|
+
user.name #=> 'Blinky'
|
27
39
|
user.email #=> "unknown@example.com"
|
28
40
|
user.created_at #=> 2017-07-14 03:40:00 +0100
|
29
41
|
user.age #=> 21
|
@@ -32,6 +44,10 @@ user.twitter_handle #=> nil
|
|
32
44
|
user.favorite_ice_cream #=> "chocolate"
|
33
45
|
user.favorite_ice_cream #=> "chocolate"
|
34
46
|
user.reload.favorite_ice_cream #=> "vanilla"
|
47
|
+
|
48
|
+
user.try_another_flavor!
|
49
|
+
#=> Blinky currently likes vanilla.
|
50
|
+
#=> Blinky just tried strawberry. They love it!
|
35
51
|
```
|
36
52
|
|
37
53
|
<p align="center">
|
data/lib/lazy_lazer.rb
CHANGED
@@ -60,6 +60,11 @@ module LazyLazer
|
|
60
60
|
|
61
61
|
# The methods to extend the instance with.
|
62
62
|
module InstanceMethods
|
63
|
+
extend Forwardable
|
64
|
+
|
65
|
+
def_delegators :@_lazer_model, :to_h, :inspect, :read_attribute, :write_attribute, :fully_loaded?, :fully_loaded!, :not_fully_loaded!, :invalidate, :exists_locally?
|
66
|
+
private :fully_loaded!, :not_fully_loaded!, :invalidate, :exists_locally?
|
67
|
+
|
63
68
|
# Create a new instance of the class from a set of source attributes.
|
64
69
|
# @param attributes [Hash] the model attributes
|
65
70
|
# @return [void]
|
@@ -82,34 +87,6 @@ module LazyLazer
|
|
82
87
|
true
|
83
88
|
end
|
84
89
|
|
85
|
-
# Converts all the attributes that haven't been converted yet and returns the final hash.
|
86
|
-
# @return [Hash] a hash representation of the model
|
87
|
-
def to_h
|
88
|
-
@_lazer_model.parent_to_h
|
89
|
-
end
|
90
|
-
|
91
|
-
# @return [String] a human-friendly view of the model
|
92
|
-
def inspect
|
93
|
-
@_lazer_model.parent_inspect
|
94
|
-
end
|
95
|
-
|
96
|
-
# Reload the object. Calls {#lazer_reload}, then merges the results into the internal store.
|
97
|
-
# Also clears out the internal cache.
|
98
|
-
# @return [self] the updated object
|
99
|
-
def reload
|
100
|
-
new_attributes = lazer_reload.to_h
|
101
|
-
@_lazer_model.merge!(new_attributes)
|
102
|
-
self
|
103
|
-
end
|
104
|
-
|
105
|
-
# Return the value of the attribute.
|
106
|
-
# @param key_name [Symbol] the attribute name
|
107
|
-
# @return [Object] the returned value
|
108
|
-
# @raise MissingAttribute if the key was not found
|
109
|
-
def read_attribute(key_name)
|
110
|
-
@_lazer_model.read_attribute(key_name.to_sym)
|
111
|
-
end
|
112
|
-
|
113
90
|
# Return the value of the attribute, returning nil if not found.
|
114
91
|
# @param key_name [Symbol] the attribute name
|
115
92
|
# @return [Object] the returned value
|
@@ -119,14 +96,6 @@ module LazyLazer
|
|
119
96
|
nil
|
120
97
|
end
|
121
98
|
|
122
|
-
# Update an attribute.
|
123
|
-
# @param key_name [Symbol] the attribute to update
|
124
|
-
# @param new_value [Object] the new value
|
125
|
-
# @return [Object] the written value
|
126
|
-
def write_attribute(key_name, new_value)
|
127
|
-
@_lazer_model.write_attribute(key_name, new_value)
|
128
|
-
end
|
129
|
-
|
130
99
|
# Update multiple attributes at once.
|
131
100
|
# @param new_attributes [Hash<Symbol, Object>] the new attributes
|
132
101
|
# @return [self] the updated object
|
@@ -136,9 +105,13 @@ module LazyLazer
|
|
136
105
|
end
|
137
106
|
alias attributes= assign_attributes
|
138
107
|
|
139
|
-
#
|
140
|
-
|
141
|
-
|
108
|
+
# Reload the object. Calls {#lazer_reload}, then merges the results into the internal store.
|
109
|
+
# Also clears out the internal cache.
|
110
|
+
# @return [self] the updated object
|
111
|
+
def reload
|
112
|
+
new_attributes = lazer_reload.to_h
|
113
|
+
@_lazer_model.merge!(new_attributes)
|
114
|
+
self
|
142
115
|
end
|
143
116
|
|
144
117
|
private
|
@@ -146,27 +119,7 @@ module LazyLazer
|
|
146
119
|
# @abstract Provides reloading behaviour for lazy loading.
|
147
120
|
# @return [Hash] the result of reloading the hash
|
148
121
|
def lazer_reload
|
149
|
-
fully_loaded!
|
150
122
|
{}
|
151
123
|
end
|
152
|
-
|
153
|
-
# Mark a key as tainted, forcing a reload on the next lookup.
|
154
|
-
# @param key_name [Symbol] the key to invalidate
|
155
|
-
# @return [void]
|
156
|
-
def invalidate(key_name)
|
157
|
-
@_lazer_model.invalidate(key_name)
|
158
|
-
end
|
159
|
-
|
160
|
-
# Mark the model as fully loaded.
|
161
|
-
# @return [void]
|
162
|
-
def fully_loaded!
|
163
|
-
@_lazer_model.fully_loaded = true
|
164
|
-
end
|
165
|
-
|
166
|
-
# Mark the model as not fully loaded.
|
167
|
-
# @return [void]
|
168
|
-
def not_fully_loaded!
|
169
|
-
@_lazer_model.fully_loaded = false
|
170
|
-
end
|
171
124
|
end
|
172
125
|
end
|
@@ -3,9 +3,6 @@
|
|
3
3
|
module LazyLazer
|
4
4
|
# A delegator for internal operations.
|
5
5
|
class InternalModel
|
6
|
-
# @return [Boolean] whether the model is fully loaded
|
7
|
-
attr_accessor :fully_loaded
|
8
|
-
|
9
6
|
# Create an internal model with a reference to a public model.
|
10
7
|
# @param key_metadata [KeyMetadataStore] a reference to a metadata store
|
11
8
|
# @param parent [LazyLazer] a reference to a LazyLazer model
|
@@ -18,34 +15,27 @@ module LazyLazer
|
|
18
15
|
@fully_loaded = false
|
19
16
|
end
|
20
17
|
|
21
|
-
# Verify that all the keys marked as required are present.
|
22
|
-
# @raise RequiredAttribute if a required attribute is missing
|
23
|
-
# @return [void]
|
24
|
-
def verify_required!
|
25
|
-
@key_metadata.required_properties.each do |key_name|
|
26
|
-
next if @source_hash.key?(@key_metadata.get(key_name).source_key)
|
27
|
-
raise RequiredAttribute, "#{@parent} requires `#{key_name}`"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return [Array] the identity properties
|
32
|
-
def required_properties
|
33
|
-
@key_metadata.required_properties
|
34
|
-
end
|
35
|
-
|
36
18
|
# Converts all unconverted keys and packages them as a hash.
|
37
19
|
# @return [Hash] the converted hash
|
38
|
-
def
|
20
|
+
def to_h
|
39
21
|
todo = @key_metadata.keys - @cache_hash.keys
|
40
22
|
todo.each_with_object(@cache_hash) { |key, cache| cache[key] = load_key_from_source(key) }.dup
|
41
23
|
end
|
42
24
|
|
43
25
|
# @return [String] the string representation of the parent
|
44
|
-
def
|
26
|
+
def inspect
|
45
27
|
"#<#{@parent.class.name} (#{@fully_loaded ? 'loaded' : 'unloaded'}): [" + \
|
46
28
|
@cache_hash.keys.join(', ') + ']>'
|
47
29
|
end
|
48
30
|
|
31
|
+
# Whether the key doesn't need to be lazily loaded.
|
32
|
+
# @param key_name [Symbol] the key to check
|
33
|
+
# @return [Boolean] whether the key exists locally.
|
34
|
+
def exists_locally?(key_name)
|
35
|
+
ensure_metadata_exists(key_name)
|
36
|
+
@source_hash.key?(@key_metadata.get(key_name).source_key)
|
37
|
+
end
|
38
|
+
|
49
39
|
# Mark a key as tainted, forcing a reload on the next lookup.
|
50
40
|
# @param key_name [Symbol] the key to invalidate
|
51
41
|
# @return [void]
|
@@ -58,11 +48,12 @@ module LazyLazer
|
|
58
48
|
# @return [Object] the returned value
|
59
49
|
# @raise MissingAttribute if the attribute wasn't found and there isn't a default
|
60
50
|
def read_attribute(key_name)
|
61
|
-
|
51
|
+
key_name_sym = key_name.to_sym
|
52
|
+
if @invalidated.include?(key_name_sym)
|
62
53
|
@parent.reload
|
63
|
-
@invalidated.delete(
|
54
|
+
@invalidated.delete(key_name_sym)
|
64
55
|
end
|
65
|
-
@cache_hash[
|
56
|
+
@cache_hash[key_name_sym] ||= load_key_from_source(key_name_sym)
|
66
57
|
end
|
67
58
|
|
68
59
|
# Update an attribute.
|
@@ -76,7 +67,42 @@ module LazyLazer
|
|
76
67
|
@cache_hash[key_name] = new_value
|
77
68
|
end
|
78
69
|
|
70
|
+
# Mark the model as fully loaded.
|
71
|
+
# @return [void]
|
72
|
+
def fully_loaded!
|
73
|
+
@fully_loaded = true
|
74
|
+
end
|
75
|
+
|
76
|
+
# Mark the model as not fully loaded.
|
77
|
+
# @return [void]
|
78
|
+
def not_fully_loaded!
|
79
|
+
@fully_loaded = false
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Boolean] whether the object is done with lazy loading
|
83
|
+
def fully_loaded?
|
84
|
+
@fully_loaded
|
85
|
+
end
|
86
|
+
|
87
|
+
# Verify that all the keys marked as required are present.
|
88
|
+
# @api private
|
89
|
+
# @raise RequiredAttribute if a required attribute is missing
|
90
|
+
# @return [void]
|
91
|
+
def verify_required!
|
92
|
+
@key_metadata.required_properties.each do |key_name|
|
93
|
+
next if @source_hash.key?(@key_metadata.get(key_name).source_key)
|
94
|
+
raise RequiredAttribute, "#{@parent} requires `#{key_name}`"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @api private
|
99
|
+
# @return [Array] the identity properties
|
100
|
+
def required_properties
|
101
|
+
@key_metadata.required_properties
|
102
|
+
end
|
103
|
+
|
79
104
|
# Merge a hash into the model.
|
105
|
+
# @api private
|
80
106
|
# @param attributes [Hash<Symbol, Object>] the attributes to merge
|
81
107
|
def merge!(attributes)
|
82
108
|
@cache_hash.clear
|
@@ -9,10 +9,10 @@ module LazyLazer
|
|
9
9
|
attr_accessor :source_key
|
10
10
|
|
11
11
|
# @return [Boolean] whether the key must exist when creating the model
|
12
|
-
|
12
|
+
attr_writer :required
|
13
13
|
|
14
14
|
# @return [Boolean] whether the key must exist when loaded
|
15
|
-
|
15
|
+
attr_writer :runtime_required
|
16
16
|
|
17
17
|
# @return [Proc, Object] the default value or generator
|
18
18
|
attr_accessor :default
|
data/lib/lazy_lazer/version.rb
CHANGED