volt-repo_cache 0.1.6 → 0.1.7
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/lib/volt/repo_cache/association.rb +0 -3
- data/lib/volt/repo_cache/cache.rb +0 -9
- data/lib/volt/repo_cache/collection.rb +40 -54
- data/lib/volt/repo_cache/model.rb +93 -75
- data/lib/volt/repo_cache/model_array.rb +1 -4
- data/lib/volt/repo_cache/util.rb +1 -10
- data/lib/volt/repo_cache/version.rb +1 -1
- data/volt-repo_cache.gemspec +0 -17
- metadata +3 -185
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6e67fb69f5462671adbe6c70c7d88ff76156bc7
|
4
|
+
data.tar.gz: b7dacb4047656a539f2cc858f5ae88f955185d0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6438cc77fd305a203677d88ae2805a538fcebb3c672ea1a8e4ad735c1631f191557ca47a4102508692a3786c5e8584c19b94d11637cdf3de6714fb9038b7257
|
7
|
+
data.tar.gz: de00eae7965eb73757fcd19154fab9c8159e345355ecbef617d2af9091158c9ae061f5bfeec206a45887c9a428dfd9933e0e7147edc847cacaa117ead803f748
|
@@ -58,13 +58,10 @@ module Volt
|
|
58
58
|
# foreign_collection being lazily initialized.
|
59
59
|
def reciprocal
|
60
60
|
unless @reciprocal
|
61
|
-
# debug __method__, __LINE__, ""
|
62
61
|
@reciprocal = foreign_collection.associations.values.detect do |a|
|
63
|
-
# debug __method__, __LINE__, "#{a.foreign_collection.name} ?==? #{local_collection.name}"
|
64
62
|
a.foreign_collection.name == local_collection.name
|
65
63
|
end
|
66
64
|
@reciprocal = :nil unless @reciprocal
|
67
|
-
# debug __method__, __LINE__, "reciprocal of #{self.inspect} is #{@reciprocal.inspect}"
|
68
65
|
end
|
69
66
|
@reciprocal == :nil ? nil : @reciprocal
|
70
67
|
end
|
@@ -36,7 +36,6 @@ module Volt
|
|
36
36
|
# read_only should be inherited by has_... targets
|
37
37
|
#
|
38
38
|
def initialize(**options)
|
39
|
-
# debug __method__, __LINE__, "@options = #{@options}"
|
40
39
|
@repo = options.delete(:repo) || Volt.current_app.store
|
41
40
|
@collection_options = options.delete(:collections) || {}
|
42
41
|
load
|
@@ -62,7 +61,6 @@ module Volt
|
|
62
61
|
def clear
|
63
62
|
# debug __method__, __LINE__
|
64
63
|
@collections.each do |name, collection|
|
65
|
-
# debug __method__, __LINE__, "name=#{name} collection=#{collection}"
|
66
64
|
collection.send(:uncache)
|
67
65
|
end
|
68
66
|
@collections = {}
|
@@ -90,20 +88,13 @@ module Volt
|
|
90
88
|
promises = []
|
91
89
|
@collection_options.each do |given_name, options|
|
92
90
|
name = collection_name(given_name)
|
93
|
-
# debug __method__, __LINE__
|
94
91
|
collection = Collection.new(cache: self, name: name, options: options)
|
95
|
-
# debug __method__, __LINE__
|
96
92
|
@collections[name] = collection
|
97
93
|
promises << collection.loaded
|
98
94
|
end
|
99
|
-
# debug __method__, __LINE__, "promises.size = #{promises.size}"
|
100
|
-
t1 = Time.now
|
101
95
|
@loaded = Promise.when(*promises).then do
|
102
|
-
# t2 = Time.now
|
103
|
-
# debug __method__, __LINE__, "@@loaded = Promise.when(*promises).then took #{t2-t1} seconds"
|
104
96
|
self
|
105
97
|
end
|
106
|
-
# debug __method__, __LINE__, "@loaded => #{@loaded.class.name}:#{@loaded.value.class.name}"
|
107
98
|
end
|
108
99
|
|
109
100
|
def collection_name(given_name)
|
@@ -13,16 +13,14 @@ module Volt
|
|
13
13
|
attr_reader :model_class
|
14
14
|
attr_reader :repo_collection
|
15
15
|
attr_reader :load_query
|
16
|
-
attr_reader :
|
16
|
+
attr_reader :cached_ids
|
17
17
|
attr_reader :loaded # Promise
|
18
18
|
attr_reader :marked_for_destruction
|
19
19
|
attr_reader :associations
|
20
20
|
attr_reader :read_only
|
21
21
|
|
22
22
|
def initialize(cache: nil, name: nil, options: {})
|
23
|
-
# debug __method__, __LINE__, "name: #{name} options: #{options}"
|
24
23
|
super(observer: self)
|
25
|
-
# debug __method__, __LINE__
|
26
24
|
@cache = cache
|
27
25
|
@name = name
|
28
26
|
@load_query = options[:query] || options[:where]
|
@@ -33,7 +31,6 @@ module Volt
|
|
33
31
|
@repo_collection = @cache.repo.send(name)
|
34
32
|
init_associations(options)
|
35
33
|
load
|
36
|
-
# debug __method__, __LINE__
|
37
34
|
end
|
38
35
|
|
39
36
|
# hide circular reference to cache
|
@@ -70,7 +67,7 @@ module Volt
|
|
70
67
|
append(hash.to_h)
|
71
68
|
end
|
72
69
|
|
73
|
-
# Appends a model to the collection.
|
70
|
+
# Appends a new model to the collection.
|
74
71
|
# Model may be a hash which will be converted.
|
75
72
|
# (See #induct for more.)
|
76
73
|
# If the model belongs_to any other owners, the foreign id(s)
|
@@ -78,8 +75,8 @@ module Volt
|
|
78
75
|
# in the cache - it is easier to ask the owner for a new
|
79
76
|
# instance (e.g. product.recipe.new_ingredient).
|
80
77
|
# NB: Returns the newly appended model.
|
81
|
-
def append(model,
|
82
|
-
model = induct(model,
|
78
|
+
def append(model, notify: true)
|
79
|
+
model = induct(model, loaded_from_repo: false)
|
83
80
|
__append__(model, notify: notify)
|
84
81
|
model
|
85
82
|
end
|
@@ -123,7 +120,7 @@ module Volt
|
|
123
120
|
# Remove model from marked_for_destruction bucket.
|
124
121
|
# Don't worry if we can't find it.
|
125
122
|
def destroyed(model)
|
126
|
-
@
|
123
|
+
@cached_ids.delete(model.id)
|
127
124
|
@marked_for_destruction.delete(model.id)
|
128
125
|
end
|
129
126
|
|
@@ -131,17 +128,13 @@ module Volt
|
|
131
128
|
# that a model has been added or removed. Pass
|
132
129
|
# this on to associations.
|
133
130
|
def observe(action, model)
|
134
|
-
# debug __method__, __LINE__, "action=#{action} model=#{model} associations=#{associations}"
|
135
131
|
# notify owner model(s) of appended model that it has been added
|
136
132
|
notify_associations(action, model)
|
137
133
|
end
|
138
134
|
|
139
135
|
def notify_associations(action, model)
|
140
|
-
# debug __method__, __LINE__, "action=#{action} model=#{model} associations=#{associations}"
|
141
136
|
associations.each_value do |assoc|
|
142
|
-
# debug __method__, __LINE__, "calling notify_associates(#{assoc}, #{action}, #{model})"
|
143
137
|
notify_associates(assoc, action, model)
|
144
|
-
# debug __method__, __LINE__, "called notify_associates(#{assoc}, #{action}, #{model})"
|
145
138
|
end
|
146
139
|
end
|
147
140
|
|
@@ -152,22 +145,17 @@ module Volt
|
|
152
145
|
# association may be owner customer - thus
|
153
146
|
# association will be belongs_to
|
154
147
|
def notify_associates(assoc, action, model)
|
155
|
-
# debug __method__, __LINE__, "action=#{action} model=#{model} assoc=#{assoc} reciprocate=#{assoc.reciprocal}"
|
156
148
|
if assoc.reciprocal
|
157
149
|
local_id = model.send(assoc.local_id_field)
|
158
|
-
# debug __method__, __LINE__, "local_id #{assoc.local_id_field}=#{local_id}"
|
159
150
|
if local_id # may not be set yet
|
160
151
|
assoc.foreign_collection.each do |other|
|
161
|
-
# debug __method__, __LINE__, "calling #{assoc.foreign_id_field} on #{other}"
|
162
152
|
foreign_id = other.send(assoc.foreign_id_field)
|
163
153
|
if local_id == foreign_id
|
164
|
-
# debug __method__, __LINE__, "foreign_id==local_id of #{other}, calling other.refresh_association(#{assoc.foreign_name})"
|
165
154
|
other.send(:refresh_association, assoc.reciprocal)
|
166
155
|
end
|
167
156
|
end
|
168
157
|
end
|
169
158
|
end
|
170
|
-
# debug __method__, __LINE__
|
171
159
|
end
|
172
160
|
|
173
161
|
# 'Induct' a model into the cache via this collection.
|
@@ -193,66 +181,64 @@ module Volt
|
|
193
181
|
# associational integrity in the cache.
|
194
182
|
#
|
195
183
|
# Returns the inducted model.
|
196
|
-
def induct(model_or_hash,
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
model = model_class.new(model_or_hash, options: {persistor: cache.persistor})
|
201
|
-
else
|
202
|
-
model = model_or_hash
|
203
|
-
# unless model.persistor.class == cache.persistor.class
|
204
|
-
# raise RuntimeError, "model persistor is #{model.persistor} but should be #{cache.persistor}"
|
205
|
-
# end
|
206
|
-
unless model.class == model_class
|
207
|
-
raise ArgumentError, "#{model} must be a #{model_class_name}"
|
208
|
-
end
|
209
|
-
if error_unless_new && (!model.created_in_cache? || model.new?)
|
210
|
-
raise ArgumentError, "#{model} must be new (not stored) or have been created in cache"
|
184
|
+
def induct(model_or_hash, loaded_from_repo: false)
|
185
|
+
model = if Hash === model_or_hash
|
186
|
+
if loaded_from_repo
|
187
|
+
raise TypeError, "cannot induct stored model from a hash #{model_or_hash}"
|
211
188
|
end
|
212
|
-
|
213
|
-
|
189
|
+
model_class.new(model_or_hash, options: {persistor: cache.persistor})
|
190
|
+
else
|
191
|
+
if !loaded_from_repo && model_or_hash.buffer?
|
192
|
+
raise TypeError, "cannot induct new model_or_hash #{model_or_hash} with buffer"
|
214
193
|
end
|
194
|
+
model_or_hash
|
195
|
+
end
|
196
|
+
unless model.class == model_class
|
197
|
+
raise ArgumentError, "#{model} must be a #{model_class_name}"
|
198
|
+
end
|
199
|
+
if model.cached?
|
200
|
+
__debug __method__, __LINE__, "id=#{model.id} model.cached?=#{model.cached?}"
|
201
|
+
raise TypeError, "model.id #{model.id} already in cache"
|
215
202
|
end
|
216
|
-
@
|
217
|
-
|
203
|
+
@cached_ids << model.id
|
204
|
+
RepoCache::Model.induct_to_cache(model, self, loaded_from_repo)
|
218
205
|
model
|
219
206
|
end
|
220
207
|
|
208
|
+
def cached?(model)
|
209
|
+
@cached_ids.include?(model.id)
|
210
|
+
end
|
211
|
+
|
221
212
|
def load
|
222
|
-
#
|
223
|
-
@loaded_ids = Set.new # append/delete will update
|
213
|
+
@cached_ids = Set.new # append/delete will update
|
224
214
|
q = @load_query ? repo_collection.where(@load_query) : repo_collection
|
225
|
-
# t1 = Time.now
|
226
215
|
@loaded = q.all.collect{|e|e}.then do |models|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
216
|
+
models.each do |_model|
|
217
|
+
model = read_only ? _model : _model.buffer
|
218
|
+
induct(model, loaded_from_repo: true)
|
219
|
+
__append__(model, notify: false)
|
231
220
|
end
|
232
|
-
# t3 = Time.now
|
233
|
-
# debug __method__, __LINE__, "#{name} loaded ids for #{models.size} #{name} in #{t3-t2} seconds"
|
234
221
|
self
|
235
222
|
end
|
236
|
-
# debug __method__, __LINE__, "@loaded => #{@loaded.class.name}:#{@loaded.value.class.name}"
|
237
223
|
end
|
238
224
|
|
239
225
|
def init_associations(options)
|
240
|
-
# debug __method__, __LINE__, "options = #{options}"
|
241
226
|
@associations = {}
|
242
227
|
[:belongs_to, :has_one, :has_many].each do |type|
|
243
228
|
arrify(options[type]).map(&:to_sym).each do |foreign_name|
|
244
229
|
@associations[foreign_name] = Association.new(self, foreign_name, type)
|
245
|
-
# debug __method__, __LINE__, "@associations[#{foreign_name}] = #{@associations[foreign_name].inspect}"
|
246
230
|
end
|
247
231
|
end
|
248
232
|
end
|
249
233
|
|
250
|
-
def
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
234
|
+
def __debug(method, line, msg = nil)
|
235
|
+
s = "{__FILE__}[#{line}]:#{self.class.name}##{method}: #{msg}"
|
236
|
+
if RUBY_PLATFORM == 'opal'
|
237
|
+
Volt.logger.debug s
|
238
|
+
else
|
239
|
+
puts s
|
240
|
+
end
|
241
|
+
end
|
256
242
|
|
257
243
|
end
|
258
244
|
end
|
@@ -4,19 +4,31 @@
|
|
4
4
|
# methods to the module and provides
|
5
5
|
# the instance as argument.
|
6
6
|
|
7
|
+
module Volt
|
8
|
+
class Model
|
9
|
+
def stored?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def cached?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
7
19
|
module Volt
|
8
20
|
module RepoCache
|
9
21
|
module Model
|
10
22
|
extend Volt::RepoCache::Util
|
11
23
|
|
12
|
-
def self.
|
13
|
-
#
|
24
|
+
def self.induct_to_cache(model, collection, loaded_from_repo)
|
25
|
+
# debug_model __method__, __LINE__, "patch_for_cache [#{collection.name}] : #{model.to_h}"
|
14
26
|
|
15
27
|
# Volt sets @new to false if any attribute changes - not what we want
|
16
|
-
model.instance_variable_set(:@
|
17
|
-
model.instance_variable_set(:@
|
18
|
-
model.instance_variable_set(:@
|
19
|
-
model.instance_variable_set(:@
|
28
|
+
model.instance_variable_set(:@cache__stored, loaded_from_repo)
|
29
|
+
model.instance_variable_set(:@cache__collection, collection)
|
30
|
+
model.instance_variable_set(:@cache__associations, {})
|
31
|
+
model.instance_variable_set(:@cache__marked_for_destruction, false)
|
20
32
|
# TODO: if model is not buffered, then trap all
|
21
33
|
# field set value methods and raise exception -
|
22
34
|
# unless buffered the model is read only.
|
@@ -47,7 +59,7 @@ module Volt
|
|
47
59
|
# e.g. product.recipe
|
48
60
|
m = foreign_name
|
49
61
|
model.define_singleton_method(m) do
|
50
|
-
#
|
62
|
+
# debug_model __method__, __LINE__, "defining #{model.class.name}##{m}"
|
51
63
|
get_association(assoc)
|
52
64
|
end
|
53
65
|
|
@@ -99,34 +111,38 @@ module Volt
|
|
99
111
|
true
|
100
112
|
end
|
101
113
|
|
102
|
-
def model.
|
103
|
-
@
|
114
|
+
def model.stored?
|
115
|
+
@cache__stored
|
104
116
|
end
|
105
117
|
|
106
118
|
# Returns true if the model has been marked
|
107
119
|
# for destruction on flush. Otherwise false.
|
108
120
|
def model.marked_for_destruction?
|
109
|
-
@
|
121
|
+
@cache__marked_for_destruction
|
122
|
+
end
|
123
|
+
|
124
|
+
def model.cached?
|
125
|
+
@cache__collection.cached?(self)
|
110
126
|
end
|
111
127
|
|
112
128
|
# Returns the cached collected the model belongs to.
|
113
129
|
def model.collection
|
114
|
-
@
|
130
|
+
@cache__collection
|
115
131
|
end
|
116
132
|
|
117
133
|
# Returns the cache the model belongs to.
|
118
134
|
def model.cache
|
119
|
-
@
|
135
|
+
@cache__collection.cache
|
120
136
|
end
|
121
137
|
|
122
138
|
# Hide circular reference to collection
|
123
139
|
# when doing inspection.
|
124
140
|
def model.inspect
|
125
|
-
if @
|
126
|
-
__tmp = @
|
127
|
-
@
|
141
|
+
if @cache__collection
|
142
|
+
__tmp = @cache__collection
|
143
|
+
@cache__collection = "{{#{@cache__collection.name}}}"
|
128
144
|
result = super
|
129
|
-
@
|
145
|
+
@cache__collection = __tmp
|
130
146
|
result
|
131
147
|
else
|
132
148
|
super
|
@@ -147,10 +163,10 @@ module Volt
|
|
147
163
|
# prevent collection going in circles on this
|
148
164
|
# (we don't know whether initial request was to
|
149
165
|
# self or to collection which holds self)
|
150
|
-
unless @
|
151
|
-
#
|
152
|
-
@
|
153
|
-
@
|
166
|
+
unless @cache__marked_for_destruction
|
167
|
+
# debug_model __method__, __LINE__, "marking #{self} for destruction"
|
168
|
+
@cache__marked_for_destruction = true
|
169
|
+
@cache__collection.send(:mark_model_for_destruction, self)
|
154
170
|
mark_associations_for_destruction
|
155
171
|
end
|
156
172
|
end
|
@@ -173,22 +189,23 @@ module Volt
|
|
173
189
|
# - any part of it may fail without unwinding the whole
|
174
190
|
def model.flush!
|
175
191
|
fail_if_read_only(__method__)
|
176
|
-
if @
|
177
|
-
#
|
192
|
+
if @cache__marked_for_destruction
|
193
|
+
# debug_model __method__, __LINE__, "marked for destruction so call destroy on #{to_h}"
|
178
194
|
__destroy__
|
179
195
|
else
|
180
|
-
if
|
181
|
-
|
182
|
-
if
|
183
|
-
#
|
184
|
-
@__cache__created_in_cache = false
|
185
|
-
@__cache__collection.repo_collection << self
|
186
|
-
else
|
187
|
-
# debug __method__, __LINE__,"dirty: #{self.class.name}::#{self.id}"
|
196
|
+
if dirty?
|
197
|
+
debug_model __method__, __LINE__, "@cache__stored=#{@cache__stored} dirty?=#{dirty?} to_h=#{to_h}"
|
198
|
+
if stored?
|
199
|
+
# debug_model __method__, __LINE__,"dirty: #{self.class.name}::#{self.id}"
|
188
200
|
__save__
|
201
|
+
else
|
202
|
+
debug_model __method__, __LINE__, "<< to repo: #{self.class.name}::#{self.to_h}"
|
203
|
+
@cache__stored = true
|
204
|
+
@cache__collection.repo_collection << self
|
205
|
+
# TODO: big problem! once new model saved it should become buffer in cache!
|
189
206
|
end
|
190
207
|
else
|
191
|
-
#
|
208
|
+
# debug_model __method__, __LINE__, "not dirty: #{to_h}"
|
192
209
|
# neither new nor dirty but
|
193
210
|
# stay in the promise chain
|
194
211
|
Promise.value(self)
|
@@ -208,7 +225,8 @@ module Volt
|
|
208
225
|
self.class.fields_data.keys.each do |field|
|
209
226
|
return true if changed?(field)
|
210
227
|
end
|
211
|
-
|
228
|
+
# if not stored then I'm dirty
|
229
|
+
!@cache__stored
|
212
230
|
end
|
213
231
|
|
214
232
|
# Destroys (deletes) the model in database.
|
@@ -252,7 +270,7 @@ module Volt
|
|
252
270
|
# #######################################
|
253
271
|
|
254
272
|
def model.fail_if_read_only(what)
|
255
|
-
if @
|
273
|
+
if @cache__collection.read_only
|
256
274
|
raise RuntimeError, "cannot #{what} for read only cache collection/model"
|
257
275
|
end
|
258
276
|
end
|
@@ -260,26 +278,26 @@ module Volt
|
|
260
278
|
|
261
279
|
# private
|
262
280
|
def model.uncache
|
263
|
-
@
|
281
|
+
@cache__associations.clear if @cache__associations
|
264
282
|
if false
|
265
283
|
instance_variables.each do |v|
|
266
284
|
if v.to_s =~ /__cache__/
|
267
|
-
#
|
285
|
+
# debug_model __method__, __LINE__, "removing instance variable '#{v}'"
|
268
286
|
set_instance_variable(v, nil)
|
269
287
|
end
|
270
288
|
end
|
271
289
|
elsif false
|
272
|
-
@
|
290
|
+
@cache__associations.clear if @cache__associations
|
273
291
|
instance_variables.each do |v|
|
274
292
|
if v.to_s =~ /__cache__/
|
275
|
-
#
|
293
|
+
# debug_model __method__, __LINE__, "removing instance variable '#{v}'"
|
276
294
|
remove_instance_variable(v)
|
277
295
|
end
|
278
296
|
end
|
279
297
|
# WARNING - assumes no singleton methods other than those we've attached
|
280
298
|
singleton_methods.each do |m|
|
281
|
-
unless m == :
|
282
|
-
#
|
299
|
+
unless m == :debug_model || m == :uncache
|
300
|
+
# debug_model __method__, __LINE__, "removing singleton method '#{m}'"
|
283
301
|
@@___m___ = m # m is out of scope in class << self TODO: anything nicer?
|
284
302
|
class << self # weird syntax to remove singleton method
|
285
303
|
remove_method(@@___m___)
|
@@ -288,7 +306,7 @@ module Volt
|
|
288
306
|
end
|
289
307
|
@@___m___ = nil
|
290
308
|
class << self
|
291
|
-
remove_method(:
|
309
|
+
remove_method(:debug_model)
|
292
310
|
remove_method(:uncache)
|
293
311
|
end
|
294
312
|
end
|
@@ -302,10 +320,10 @@ module Volt
|
|
302
320
|
#
|
303
321
|
# Raise error unless caller's class namespace is Volt::RepoCache.
|
304
322
|
def model.refresh_association(association)
|
305
|
-
#
|
323
|
+
# debug_model __method__, __LINE__, "association=#{association.foreign_name}"
|
306
324
|
# refresh the association query
|
307
325
|
result = get_association(association, refresh: true)
|
308
|
-
#
|
326
|
+
# debug_model __method__, __LINE__, "#{self} association=#{association} result=#{result}"
|
309
327
|
end
|
310
328
|
model.singleton_class.send(:private, :refresh_association)
|
311
329
|
|
@@ -322,22 +340,22 @@ module Volt
|
|
322
340
|
# (e.g. console) running.
|
323
341
|
# Returns a promise with destroyed model proxy as value.
|
324
342
|
def model.__destroy__
|
325
|
-
#
|
343
|
+
# debug_model __method__, __LINE__
|
326
344
|
fail_if_read_only(__method__)
|
327
|
-
#
|
328
|
-
promise = if
|
329
|
-
Promise.value(self)
|
330
|
-
else
|
345
|
+
# debug_model __method__, __LINE__
|
346
|
+
promise = if stored?
|
331
347
|
destroy(caller: self)
|
348
|
+
else
|
349
|
+
Promise.value(self)
|
332
350
|
end
|
333
|
-
#
|
351
|
+
# debug_model __method__, __LINE__
|
334
352
|
promise.then do |m|
|
335
|
-
#
|
336
|
-
@
|
353
|
+
# debug_model __method__, __LINE__, "destroy promise resolved to #{m}"
|
354
|
+
@cache__collection.destroyed(self)
|
337
355
|
uncache
|
338
356
|
self
|
339
357
|
end.fail do |errors|
|
340
|
-
#
|
358
|
+
# debug_model __method__, __LINE__, "destroy failed => #{errors}"
|
341
359
|
errors
|
342
360
|
end
|
343
361
|
end
|
@@ -355,23 +373,23 @@ module Volt
|
|
355
373
|
# Relies on cached collections notifying
|
356
374
|
# associated models when to refresh.
|
357
375
|
def model.get_association(assoc, refresh: false)
|
358
|
-
#
|
376
|
+
# debug_model __method__, __LINE__, "#{self.class.name}:#{id} assoc=#{assoc.foreign_name} refresh: #{refresh}"
|
359
377
|
foreign_name = assoc.foreign_name
|
360
|
-
@
|
361
|
-
prior = @
|
378
|
+
@cache__associations[foreign_name] = nil if refresh
|
379
|
+
prior = @cache__associations[foreign_name]
|
362
380
|
local_id = self.send(assoc.local_id_field)
|
363
381
|
foreign_id_field = assoc.foreign_id_field
|
364
|
-
#
|
382
|
+
# debug_model __method__, __LINE__, "foreign_id_field=#{foreign_id_field}"
|
365
383
|
result = if prior && match?(prior, foreign_id_field, local_id)
|
366
384
|
prior
|
367
385
|
else
|
368
386
|
q = {foreign_id_field => local_id}
|
369
|
-
#
|
387
|
+
# debug_model __method__, __LINE__
|
370
388
|
r = assoc.foreign_collection.query(q) || []
|
371
|
-
#
|
372
|
-
@
|
389
|
+
# debug_model __method__, __LINE__
|
390
|
+
@cache__associations[foreign_name] = assoc.has_many? ? ModelArray.new(contents: r) : r.first
|
373
391
|
end
|
374
|
-
#
|
392
|
+
# debug_model __method__, __LINE__
|
375
393
|
result
|
376
394
|
end
|
377
395
|
model.singleton_class.send(:private, :get_association)
|
@@ -434,7 +452,7 @@ module Volt
|
|
434
452
|
# has_many then any prior associated values
|
435
453
|
# will be marked for destruction.
|
436
454
|
#
|
437
|
-
# NB we don't immediately update local @
|
455
|
+
# NB we don't immediately update local @cache__associations,
|
438
456
|
# but wait to be notified by associated collections
|
439
457
|
# of changes we make to them. This ensures that
|
440
458
|
# if changes are made to those collections that
|
@@ -536,11 +554,11 @@ module Volt
|
|
536
554
|
fail_if_read_only(__method__)
|
537
555
|
validate_ownership(assoc, other, require_foreign_id: false) do |prior_foreign_id|
|
538
556
|
# after validation we can be sure prior_foreign_id == self.id
|
539
|
-
#
|
557
|
+
# debug_model __method__, __LINE__
|
540
558
|
unless prior_foreign_id
|
541
559
|
other.send(Util.setter(assoc.foreign_id_field), id)
|
542
560
|
end
|
543
|
-
#
|
561
|
+
# debug_model __method__, __LINE__
|
544
562
|
end
|
545
563
|
end
|
546
564
|
model.singleton_class.send(:private, :set_foreign_id)
|
@@ -572,9 +590,9 @@ module Volt
|
|
572
590
|
# if it does not match this model's id. Otherwise return true
|
573
591
|
# if the foreign id is not nil. Yield to given block if provided.
|
574
592
|
def model.validate_ownership(assoc, other, require_foreign_id: true, &block)
|
575
|
-
#
|
593
|
+
# debug_model __method__, __LINE__
|
576
594
|
foreign_id = other.send(assoc.foreign_id_field)
|
577
|
-
#
|
595
|
+
# debug_model __method__, __LINE__
|
578
596
|
if (foreign_id && foreign_id != self.id) || (require_foreign_id && foreign_id.nil?)
|
579
597
|
raise RuntimeError, "#{other} should belong to #{self} or no-one else"
|
580
598
|
end
|
@@ -617,15 +635,15 @@ module Volt
|
|
617
635
|
# from flushing associates.
|
618
636
|
def model.flush_associations
|
619
637
|
promises = []
|
620
|
-
@
|
638
|
+
@cache__collection.associations.values.each do |assoc|
|
621
639
|
if assoc.has_any?
|
622
|
-
#
|
640
|
+
# debug_model __method__, __LINE__, "association => '#{association}'"
|
623
641
|
model_or_array = send(assoc.foreign_name)
|
624
|
-
#
|
642
|
+
# debug_model __method__, __LINE__, "model_or_array => '#{model_or_array}'"
|
625
643
|
Util.arrify(model_or_array).each do |model|
|
626
644
|
promises << model.flush!
|
627
645
|
end
|
628
|
-
#
|
646
|
+
# debug_model __method__, __LINE__
|
629
647
|
end
|
630
648
|
end
|
631
649
|
Promise.when(*promises)
|
@@ -636,31 +654,31 @@ module Volt
|
|
636
654
|
# Marks all has_one or has_many models for destruction
|
637
655
|
def model.mark_associations_for_destruction
|
638
656
|
fail_if_read_only(__method__)
|
639
|
-
@
|
657
|
+
@cache__collection.associations.values.each do |assoc|
|
640
658
|
if assoc.has_any?
|
641
|
-
#
|
659
|
+
# debug_model __method__, __LINE__, "association => '#{association}'"
|
642
660
|
model_or_array = send(assoc.foreign_name)
|
643
661
|
if model_or_array
|
644
|
-
#
|
662
|
+
# debug_model __method__, __LINE__, "model_or_array => '#{model_or_array}'"
|
645
663
|
Util.arrify(model_or_array).each do |model|
|
646
664
|
model.mark_for_destruction!
|
647
665
|
end
|
648
|
-
#
|
666
|
+
# debug_model __method__, __LINE__
|
649
667
|
end
|
650
668
|
end
|
651
669
|
end
|
652
670
|
end
|
653
671
|
model.singleton_class.send(:private, :mark_associations_for_destruction)
|
654
672
|
|
655
|
-
def model.
|
656
|
-
s = "
|
673
|
+
def model.debug_model(method, line, msg = nil)
|
674
|
+
s = "#{__FILE__}[#{line}]:#{self.class.name}##{method}: #{msg}"
|
657
675
|
if RUBY_PLATFORM == 'opal'
|
658
676
|
Volt.logger.debug s
|
659
677
|
else
|
660
678
|
puts s
|
661
679
|
end
|
662
680
|
end
|
663
|
-
model.singleton_class.send(:private, :
|
681
|
+
model.singleton_class.send(:private, :debug_model)
|
664
682
|
|
665
683
|
end
|
666
684
|
|
@@ -160,12 +160,9 @@ module Volt
|
|
160
160
|
def __remove__(model, error_if_absent: true)
|
161
161
|
index = index {|e| e.id == model.id }
|
162
162
|
if index
|
163
|
-
|
164
|
-
# debug __method__, __LINE__, "deleted #{result.class.name} #{result.id}"
|
165
|
-
result
|
163
|
+
__delete_at__(index)
|
166
164
|
elsif error_if_absent
|
167
165
|
msg = "could not find #{model.class.name} with id #{model.id} to delete"
|
168
|
-
# debug __method__, __LINE__, msg
|
169
166
|
raise RuntimeError, msg
|
170
167
|
end
|
171
168
|
end
|
data/lib/volt/repo_cache/util.rb
CHANGED
@@ -57,20 +57,11 @@ module Volt
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
def debug(method, line, msg = nil)
|
61
|
-
s = ">>> #{self.class.name}##{method}[#{line}] : #{msg}"
|
62
|
-
if RUBY_PLATFORM == 'opal'
|
63
|
-
Volt.logger.debug s
|
64
|
-
else
|
65
|
-
puts s
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
60
|
def time(method, line, msg = nil)
|
70
61
|
t1 = Time.now
|
71
62
|
r = yield
|
72
63
|
t2 = Time.now
|
73
|
-
debug
|
64
|
+
debug 1, ->{['nil file', line, method, "#{msg} : took #{t2 - t1} seconds"]}
|
74
65
|
r
|
75
66
|
end
|
76
67
|
end
|
data/volt-repo_cache.gemspec
CHANGED
@@ -18,21 +18,4 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "volt", "~> 0.9.6"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
|
24
|
-
# Testing gems
|
25
|
-
spec.add_development_dependency 'rspec', '~> 3.2.0'
|
26
|
-
spec.add_development_dependency 'opal-rspec', '~> 0.4.2'
|
27
|
-
spec.add_development_dependency 'capybara', '~> 2.4.4'
|
28
|
-
spec.add_development_dependency 'selenium-webdriver', '~> 2.47.0'
|
29
|
-
spec.add_development_dependency 'chromedriver-helper', '~> 1.0.0'
|
30
|
-
spec.add_development_dependency 'poltergeist', '~> 1.6.0'
|
31
|
-
|
32
|
-
# Gems to run the dummy app
|
33
|
-
spec.add_development_dependency 'volt-mongo', '0.1.1'
|
34
|
-
spec.add_development_dependency 'volt-bootstrap', '~> 0.1.0'
|
35
|
-
spec.add_development_dependency 'volt-bootstrap_jumbotron_theme', '~> 0.1.0'
|
36
|
-
spec.add_development_dependency 'volt-user_templates', '~> 0.4.0'
|
37
|
-
spec.add_development_dependency 'thin', '~> 1.6.0'
|
38
21
|
end
|
metadata
CHANGED
@@ -1,197 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: volt-repo_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Colin Gunn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: volt
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 0.9.6
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 0.9.6
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 3.2.0
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 3.2.0
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: opal-rspec
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.4.2
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 0.4.2
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: capybara
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 2.4.4
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 2.4.4
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: selenium-webdriver
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 2.47.0
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: 2.47.0
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: chromedriver-helper
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 1.0.0
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 1.0.0
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: poltergeist
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 1.6.0
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 1.6.0
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: volt-mongo
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - '='
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: 0.1.1
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - '='
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: 0.1.1
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: volt-bootstrap
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: 0.1.0
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - "~>"
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 0.1.0
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: volt-bootstrap_jumbotron_theme
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - "~>"
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: 0.1.0
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: 0.1.0
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: volt-user_templates
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - "~>"
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: 0.4.0
|
174
|
-
type: :development
|
175
|
-
prerelease: false
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
177
|
-
requirements:
|
178
|
-
- - "~>"
|
179
|
-
- !ruby/object:Gem::Version
|
180
|
-
version: 0.4.0
|
181
|
-
- !ruby/object:Gem::Dependency
|
182
|
-
name: thin
|
183
|
-
requirement: !ruby/object:Gem::Requirement
|
184
|
-
requirements:
|
185
|
-
- - "~>"
|
186
|
-
- !ruby/object:Gem::Version
|
187
|
-
version: 1.6.0
|
188
|
-
type: :development
|
189
|
-
prerelease: false
|
190
|
-
version_requirements: !ruby/object:Gem::Requirement
|
191
|
-
requirements:
|
192
|
-
- - "~>"
|
193
|
-
- !ruby/object:Gem::Version
|
194
|
-
version: 1.6.0
|
11
|
+
date: 2016-04-28 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
195
13
|
description: Cache multiple collections or query based subsets from any Volt repository.
|
196
14
|
Provides faster and simpler client-side processing. Reduces the burden of promise
|
197
15
|
handling. Changes - updates, creates and destroys - can be saved (flushed) back
|