lazy_lazer 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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