reactive-record 0.7.1 → 0.7.4
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/reactive_record/active_record/class_methods.rb +1 -1
- data/lib/reactive_record/active_record/reactive_record/base.rb +25 -19
- data/lib/reactive_record/active_record/reactive_record/collection.rb +68 -33
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +93 -15
- data/lib/reactive_record/server_data_cache.rb +14 -14
- data/lib/reactive_record/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7340611c4d6c163c466a2a69ae056e7f03ec5cc8
|
|
4
|
+
data.tar.gz: 12a5dd997cec60c8b9226b3877156ec07a4a0ffa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 007ed1a1b5f3ed796537f52e2bde0e28869b29887c77e6881e34978bdd1d7e72375b696e0d761b28a8f5825df5ad0ac941ce09a0e04afc5e0609b6fff46b90a9
|
|
7
|
+
data.tar.gz: fdf1e5c4faf0eba8f5b85a44209bedac7802e0ce17f9b71a3ecf21b7192177dd95295f254c0038a3e304b5c1c868de68ccfb39a378d2bc234baebf5649b8fe7d
|
|
@@ -49,15 +49,16 @@ module ReactiveRecord
|
|
|
49
49
|
@data_loading = false
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
def self.find(model, attribute, value)
|
|
53
|
-
|
|
52
|
+
def self.find(model, attribute, value)
|
|
54
53
|
# will return the unique record with this attribute-value pair
|
|
55
54
|
# value cannot be an association or aggregation
|
|
56
55
|
|
|
57
56
|
model = model.base_class
|
|
58
57
|
# already have a record with this attribute-value pair?
|
|
59
58
|
record = @records[model].detect { |record| record.attributes[attribute] == value}
|
|
60
|
-
|
|
59
|
+
if !record and attribute == 'id' and !@disabled_debugging
|
|
60
|
+
# `debugger`
|
|
61
|
+
end
|
|
61
62
|
unless record
|
|
62
63
|
# if not, and then the record may be loaded, but not have this attribute set yet,
|
|
63
64
|
# so find the id of of record with the attribute-value pair, and see if that is loaded.
|
|
@@ -95,14 +96,14 @@ module ReactiveRecord
|
|
|
95
96
|
|
|
96
97
|
def initialize(model, hash = {}, ar_instance = nil)
|
|
97
98
|
@model = model
|
|
98
|
-
@attributes = hash
|
|
99
99
|
@synced_attributes = {}
|
|
100
|
+
@attributes = hash
|
|
100
101
|
@ar_instance = ar_instance
|
|
101
102
|
records[model] << self
|
|
102
103
|
end
|
|
103
104
|
|
|
104
105
|
def find(*args)
|
|
105
|
-
self.find(*args)
|
|
106
|
+
self.class.find(*args)
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
def new_from_vector(*args)
|
|
@@ -142,7 +143,7 @@ module ReactiveRecord
|
|
|
142
143
|
end
|
|
143
144
|
|
|
144
145
|
def reactive_set!(attribute, value)
|
|
145
|
-
unless @destroyed or attributes[attribute] == value
|
|
146
|
+
unless @destroyed or (!(attributes[attribute].is_a? DummyValue) and attributes.has_key?(attribute) and attributes[attribute] == value)
|
|
146
147
|
if association = @model.reflect_on_association(attribute)
|
|
147
148
|
if association.collection?
|
|
148
149
|
collection = Collection.new(association.klass, @ar_instance, association)
|
|
@@ -153,7 +154,7 @@ module ReactiveRecord
|
|
|
153
154
|
inverse_association = association.klass.reflect_on_association(inverse_of)
|
|
154
155
|
if inverse_association.collection?
|
|
155
156
|
if !value
|
|
156
|
-
attributes[attribute].attributes[inverse_of].delete(@ar_instance)
|
|
157
|
+
attributes[attribute].attributes[inverse_of].delete(@ar_instance) if attributes[attribute]
|
|
157
158
|
elsif value.attributes[inverse_of]
|
|
158
159
|
value.attributes[inverse_of] << @ar_instance
|
|
159
160
|
else
|
|
@@ -176,14 +177,23 @@ module ReactiveRecord
|
|
|
176
177
|
end
|
|
177
178
|
|
|
178
179
|
def changed?(*args)
|
|
179
|
-
if args.count == 0
|
|
180
|
+
attrs = if args.count == 0
|
|
180
181
|
React::State.get_state(self, self)
|
|
181
|
-
@attributes
|
|
182
|
+
@attributes.dup
|
|
182
183
|
else
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
React::State.get_state(@attributes, args[0])
|
|
185
|
+
{args[0] => @attributes[args[0]]}
|
|
186
|
+
end
|
|
187
|
+
attrs.each do |attribute, value|
|
|
188
|
+
if association = @model.reflect_on_association(attribute) and association.collection? and value
|
|
189
|
+
return true unless value == @synced_attributes[attribute]
|
|
190
|
+
elsif !@synced_attributes.has_key?(attribute)
|
|
191
|
+
return true
|
|
192
|
+
elsif @synced_attributes[attribute] != value
|
|
193
|
+
return true
|
|
194
|
+
end
|
|
186
195
|
end
|
|
196
|
+
false
|
|
187
197
|
end
|
|
188
198
|
|
|
189
199
|
def sync!(hash = {})
|
|
@@ -219,18 +229,14 @@ module ReactiveRecord
|
|
|
219
229
|
end
|
|
220
230
|
|
|
221
231
|
def find_association(association, id)
|
|
222
|
-
|
|
223
232
|
inverse_of = association.inverse_of
|
|
224
|
-
|
|
225
233
|
instance = if id
|
|
226
234
|
find(association.klass, association.klass.primary_key, id)
|
|
227
235
|
else
|
|
228
236
|
new_from_vector(association.klass, nil, *vector, association.attribute)
|
|
229
237
|
end
|
|
230
|
-
|
|
231
238
|
instance_backing_record_attributes = instance.instance_variable_get(:@backing_record).attributes
|
|
232
239
|
inverse_association = association.klass.reflect_on_association(inverse_of)
|
|
233
|
-
|
|
234
240
|
if inverse_association.collection?
|
|
235
241
|
instance_backing_record_attributes[inverse_of] = if id and id != ""
|
|
236
242
|
Collection.new(@model, instance, inverse_association, association.klass, ["find", id], inverse_of)
|
|
@@ -240,7 +246,7 @@ module ReactiveRecord
|
|
|
240
246
|
instance_backing_record_attributes[inverse_of].replace [@ar_instance]
|
|
241
247
|
else
|
|
242
248
|
instance_backing_record_attributes[inverse_of] = @ar_instance
|
|
243
|
-
end if inverse_of
|
|
249
|
+
end if inverse_of and !instance_backing_record_attributes.has_key?(inverse_of)
|
|
244
250
|
instance
|
|
245
251
|
end
|
|
246
252
|
|
|
@@ -258,7 +264,7 @@ module ReactiveRecord
|
|
|
258
264
|
elsif aggregation = @model.reflect_on_aggregation(method)
|
|
259
265
|
new_from_vector(aggregation.klass, self, *vector, method)
|
|
260
266
|
elsif id and id != ""
|
|
261
|
-
self.class.fetch_from_db([@model, [:find, id], method]) || self.class.load_from_db(*vector, method)
|
|
267
|
+
value = self.class.fetch_from_db([@model, [:find, id], method]) || self.class.load_from_db(*vector, method)
|
|
262
268
|
else # its a attribute in an aggregate or we are on the client and don't know the id
|
|
263
269
|
self.class.fetch_from_db([*vector, method]) || self.class.load_from_db(*vector, method)
|
|
264
270
|
end
|
|
@@ -276,7 +282,7 @@ module ReactiveRecord
|
|
|
276
282
|
type = hash[klass.inheritance_column]
|
|
277
283
|
begin
|
|
278
284
|
return Object.const_get(type)
|
|
279
|
-
rescue
|
|
285
|
+
rescue Exception => e
|
|
280
286
|
message = "Could not subclass #{@model_klass.model_name} as #{type}. Perhaps #{type} class has not been required. Exception: #{e}"
|
|
281
287
|
`console.error(#{message})`
|
|
282
288
|
end if type
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ReactiveRecord
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
class Collection
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
def initialize(target_klass, owner = nil, association = nil, *vector)
|
|
6
6
|
if association and (association.macro != :has_many or association.klass != target_klass)
|
|
7
7
|
message = "unimplemented association #{owner} :#{association.macro} #{association.attribute}"
|
|
@@ -10,8 +10,8 @@ module ReactiveRecord
|
|
|
10
10
|
@owner = owner # can be nil if this is an outer most scope
|
|
11
11
|
@association = association
|
|
12
12
|
@target_klass = target_klass
|
|
13
|
-
if owner and !owner.id and
|
|
14
|
-
@
|
|
13
|
+
if owner and !owner.id and vector.length <= 1
|
|
14
|
+
@collection = []
|
|
15
15
|
else
|
|
16
16
|
@vector = vector.count == 0 ? [target_klass] : vector
|
|
17
17
|
end
|
|
@@ -19,82 +19,117 @@ module ReactiveRecord
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def all
|
|
22
|
+
@dummy_collection.notify if @dummy_collection
|
|
22
23
|
unless @collection
|
|
23
24
|
@collection = []
|
|
24
|
-
if ids = ReactiveRecord::Base.fetch_from_db([*@vector, "*all"])
|
|
25
|
-
ids.each do |id|
|
|
25
|
+
if ids = ReactiveRecord::Base.fetch_from_db([*@vector, "*all"])
|
|
26
|
+
ids.each do |id|
|
|
26
27
|
@collection << @target_klass.find_by(@target_klass.primary_key => id)
|
|
27
28
|
end
|
|
28
29
|
else
|
|
29
|
-
ReactiveRecord::Base.load_from_db(*@vector, "*all")
|
|
30
|
-
@
|
|
30
|
+
@dummy_collection = ReactiveRecord::Base.load_from_db(*@vector, "*all")
|
|
31
|
+
@dummy_record = ReactiveRecord::Base.new_from_vector(@target_klass, nil, *@vector, "*")
|
|
32
|
+
@dummy_record.instance_variable_get(:@backing_record).attributes[@association.inverse_of] = @owner if @association and @association.inverse_of
|
|
33
|
+
@collection << @dummy_record
|
|
31
34
|
end
|
|
32
35
|
end
|
|
33
36
|
@collection
|
|
34
37
|
end
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
|
|
37
39
|
def ==(other_collection)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
!other_collection.instance_variable_get(:@collection)
|
|
42
|
-
end
|
|
40
|
+
my_collection = (@collection || []).select { |target| target != @dummy_record }
|
|
41
|
+
other_collection = (other_collection ? (other_collection.collection || []) : []).select { |target| target != other_collection.dummy_record }
|
|
42
|
+
my_collection == other_collection
|
|
43
43
|
end
|
|
44
|
-
|
|
45
|
-
def apply_scope(scope)
|
|
44
|
+
|
|
45
|
+
def apply_scope(scope, *args)
|
|
46
46
|
# The value returned is another ReactiveRecordCollection with the scope added to the vector
|
|
47
47
|
# no additional action is taken
|
|
48
|
-
|
|
48
|
+
scope = [scope, *args] if args.count > 0
|
|
49
|
+
@scopes[scope] ||= Collection.new(@target_klass, @owner, @association, *@vector, [scope])
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
def proxy_association
|
|
52
|
-
@association
|
|
53
|
+
@association || self # returning self allows this to work with things like Model.all
|
|
53
54
|
end
|
|
54
55
|
|
|
56
|
+
def klass
|
|
57
|
+
@target_klass
|
|
58
|
+
end
|
|
59
|
+
|
|
55
60
|
|
|
56
61
|
def <<(item)
|
|
57
|
-
inverse_of = @association.inverse_of
|
|
58
|
-
if @owner and inverse_of = @association.inverse_of
|
|
62
|
+
if @owner and @association and inverse_of = @association.inverse_of
|
|
59
63
|
item.attributes[inverse_of].attributes[@association.attribute].delete(item) if item.attributes[inverse_of] and item.attributes[inverse_of].attributes[@association.attribute]
|
|
60
|
-
item.attributes[inverse_of] = @owner
|
|
64
|
+
item.attributes[inverse_of] = @owner
|
|
61
65
|
backing_record = item.instance_variable_get(:@backing_record)
|
|
62
66
|
React::State.set_state(backing_record, inverse_of, @owner) unless backing_record.data_loading?
|
|
63
67
|
end
|
|
64
68
|
all << item unless all.include? item
|
|
69
|
+
@collection.delete(@dummy_record)
|
|
70
|
+
@dummy_record = @dummy_collection = nil
|
|
65
71
|
self
|
|
66
72
|
end
|
|
67
73
|
|
|
74
|
+
[:first, :last].each do |method|
|
|
75
|
+
define_method method do |*args|
|
|
76
|
+
if args.count == 0
|
|
77
|
+
all.send(method)
|
|
78
|
+
else
|
|
79
|
+
apply_scope(method, *args)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
68
84
|
def replace(new_array)
|
|
69
|
-
return new_array if @collection == new_array
|
|
70
|
-
if @
|
|
71
|
-
|
|
85
|
+
#return new_array if @collection == new_array #not sure we need this anymore
|
|
86
|
+
@dummy_collection.notify if @dummy_collection
|
|
87
|
+
@collection.dup.each { |item| delete(item) } if @collection
|
|
88
|
+
@collection = []
|
|
89
|
+
if new_array.is_a? Collection
|
|
90
|
+
@dummy_collection = new_array.dummy_collection
|
|
91
|
+
@dummy_record = new_array.dummy_record
|
|
92
|
+
new_array.collection.each { |item| self << item } if new_array.collection
|
|
72
93
|
else
|
|
73
|
-
@
|
|
94
|
+
@dummy_collection = @dummy_record = nil
|
|
95
|
+
new_array.each { |item| self << item }
|
|
74
96
|
end
|
|
75
|
-
new_array.each { |item| self << item }
|
|
76
97
|
new_array
|
|
77
98
|
end
|
|
78
|
-
|
|
99
|
+
|
|
79
100
|
def delete(item)
|
|
80
|
-
if @owner and inverse_of = @association.inverse_of
|
|
101
|
+
if @owner and @association and inverse_of = @association.inverse_of
|
|
81
102
|
item.attributes[inverse_of] = nil
|
|
82
103
|
backing_record = item.instance_variable_get(:@backing_record)
|
|
83
104
|
React::State.set_state(backing_record, inverse_of, nil) unless backing_record.data_loading?
|
|
84
105
|
end
|
|
85
106
|
all.delete(item)
|
|
86
107
|
end
|
|
87
|
-
|
|
108
|
+
|
|
88
109
|
def method_missing(method, *args, &block)
|
|
89
110
|
if [].respond_to? method
|
|
90
111
|
all.send(method, *args, &block)
|
|
91
112
|
elsif @target_klass.respond_to? method
|
|
92
|
-
apply_scope(method)
|
|
113
|
+
apply_scope(method, *args)
|
|
93
114
|
else
|
|
94
115
|
super
|
|
95
116
|
end
|
|
96
117
|
end
|
|
97
118
|
|
|
119
|
+
protected
|
|
120
|
+
|
|
121
|
+
def dummy_record
|
|
122
|
+
@dummy_record
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def collection
|
|
126
|
+
@collection
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def dummy_collection
|
|
130
|
+
@dummy_collection
|
|
131
|
+
end
|
|
132
|
+
|
|
98
133
|
end
|
|
99
|
-
|
|
100
|
-
end
|
|
134
|
+
|
|
135
|
+
end
|
|
@@ -14,9 +14,12 @@ module ReactiveRecord
|
|
|
14
14
|
if on_opal_client?
|
|
15
15
|
@pending_fetches = []
|
|
16
16
|
@last_fetch_at = Time.now
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
unless `typeof window.ReactiveRecordInitialData === 'undefined'`
|
|
18
|
+
log(["Reactive record prerendered data being loaded: %o", `window.ReactiveRecordInitialData`])
|
|
19
|
+
JSON.from_object(`window.ReactiveRecordInitialData`).each do |hash|
|
|
20
|
+
load_from_json hash
|
|
21
|
+
end
|
|
22
|
+
end
|
|
20
23
|
end
|
|
21
24
|
end
|
|
22
25
|
end
|
|
@@ -40,8 +43,12 @@ module ReactiveRecord
|
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
prerender_footer do
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
if @server_data_cache
|
|
47
|
+
json = @server_data_cache.as_json.to_json # can this just be to_json?
|
|
48
|
+
@server_data_cache.clear_requests
|
|
49
|
+
else
|
|
50
|
+
json = {}.to_json
|
|
51
|
+
end
|
|
45
52
|
path = ::Rails.application.routes.routes.detect do |route|
|
|
46
53
|
# not sure why the second check is needed. It happens in the test app
|
|
47
54
|
route.app == ReactiveRecord::Engine or (route.app.respond_to?(:app) and route.app.app == ReactiveRecord::Engine)
|
|
@@ -54,33 +61,104 @@ module ReactiveRecord
|
|
|
54
61
|
end if RUBY_ENGINE != 'opal'
|
|
55
62
|
|
|
56
63
|
# Client side db access (never called during prerendering):
|
|
64
|
+
|
|
65
|
+
# Always returns an object of class DummyValue which will act like most standard AR field types
|
|
66
|
+
# Whenever a dummy value is accessed it notify React that there are loads pending so appropriate rerenders
|
|
67
|
+
# will occur when the value is eventually loaded.
|
|
68
|
+
|
|
57
69
|
# queue up fetches, and at the end of each rendering cycle fetch the records
|
|
58
70
|
# notify that loads are pending
|
|
59
71
|
|
|
60
72
|
def self.load_from_db(*vector)
|
|
73
|
+
return nil unless on_opal_client? # this can happen when we are on the server and a nil value is returned for an attribute
|
|
61
74
|
# only called from the client side
|
|
62
75
|
# pushes the value of vector onto the a list of vectors that will be loaded from the server when the next
|
|
63
76
|
# rendering cycle completes.
|
|
64
77
|
# takes care of informing react that there are things to load, and schedules the loader to run
|
|
65
78
|
# Note there is no equivilent to find_in_db, because each vector implicitly does a find.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
unless data_loading?
|
|
80
|
+
@pending_fetches << vector
|
|
81
|
+
schedule_fetch
|
|
82
|
+
end
|
|
83
|
+
DummyValue.new
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class DummyValue < NilClass
|
|
87
|
+
|
|
88
|
+
def notify
|
|
89
|
+
unless ReactiveRecord::Base.data_loading?
|
|
90
|
+
ReactiveRecord.loads_pending!
|
|
91
|
+
ReactiveRecord::WhileLoading.loading!
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def initialize()
|
|
96
|
+
notify
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def method_missing(method, *args, &block)
|
|
100
|
+
if 0.respond_to? method
|
|
101
|
+
notify
|
|
102
|
+
0.send(method, *args, &block)
|
|
103
|
+
elsif "".respond_to? method
|
|
104
|
+
notify
|
|
105
|
+
"".send(method, *args, &block)
|
|
106
|
+
else
|
|
107
|
+
super
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def coerce(s)
|
|
112
|
+
[self.send("to_#{s.class.name.downcase}"), s]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def ==(other_value)
|
|
116
|
+
other_value.is_a? DummyValue
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def to_s
|
|
120
|
+
notify
|
|
121
|
+
""
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def to_f
|
|
125
|
+
notify
|
|
126
|
+
0.0
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def to_i
|
|
130
|
+
notify
|
|
131
|
+
0
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def to_numeric
|
|
135
|
+
notify
|
|
136
|
+
0
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def to_date
|
|
140
|
+
"2001-01-01T00:00:00.000-00:00".to_date
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def acts_as_string?
|
|
144
|
+
true
|
|
145
|
+
end
|
|
146
|
+
|
|
72
147
|
end
|
|
148
|
+
|
|
73
149
|
|
|
74
150
|
def self.schedule_fetch
|
|
75
151
|
@fetch_scheduled ||= after(0.001) do
|
|
76
152
|
last_fetch_at = @last_fetch_at
|
|
77
|
-
|
|
153
|
+
pending_fetches = @pending_fetches.uniq
|
|
154
|
+
log(["Server Fetching: %o", pending_fetches.to_n])
|
|
155
|
+
HTTP.post(`window.ReactiveRecordEnginePath`, payload: {pending_fetches: pending_fetches}).then do |response|
|
|
78
156
|
begin
|
|
79
157
|
ReactiveRecord::Base.load_from_json(response.json)
|
|
80
158
|
rescue Exception => e
|
|
81
|
-
|
|
82
|
-
`console.error(#{message})`
|
|
159
|
+
log("Exception raised while loading json from server: #{e}", :error)
|
|
83
160
|
end
|
|
161
|
+
log([" Returned: %o", response.json.to_n])
|
|
84
162
|
ReactiveRecord.run_blocks_to_load
|
|
85
163
|
ReactiveRecord::WhileLoading.loaded_at last_fetch_at
|
|
86
164
|
end if @pending_fetches.count > 0
|
|
@@ -236,7 +314,7 @@ module ReactiveRecord
|
|
|
236
314
|
@ar_instance.send("#{association.attribute}=", nil)
|
|
237
315
|
end
|
|
238
316
|
end
|
|
239
|
-
|
|
317
|
+
|
|
240
318
|
promise = Promise.new
|
|
241
319
|
|
|
242
320
|
if id or vector
|
|
@@ -169,20 +169,24 @@ module ReactiveRecord
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
def apply_method(method)
|
|
172
|
+
method[0] = "find" if method.is_a? Array and method.first == "find_by_id"
|
|
172
173
|
new_vector = vector + [method]
|
|
173
174
|
@db_cache.detect { |cached_item| cached_item.vector == new_vector} || build_new_instances(method)
|
|
174
175
|
end
|
|
175
176
|
|
|
176
177
|
def build_new_instances(method)
|
|
177
|
-
if method == "*all"
|
|
178
|
-
apply_method_to_cache(
|
|
179
|
-
elsif method == "*"
|
|
180
|
-
@ar_object
|
|
181
|
-
|
|
178
|
+
if method == "*all"
|
|
179
|
+
apply_method_to_cache("*all") { |cache_item| cache_item.value.collect { |record| record.id } }
|
|
180
|
+
elsif method == "*"
|
|
181
|
+
if @ar_object and @ar_object.length > 0
|
|
182
|
+
@ar_object.inject(nil) do | value, record | # just using inject so we will return the last value
|
|
183
|
+
apply_method_to_cache(method) { record }
|
|
184
|
+
end
|
|
185
|
+
else
|
|
186
|
+
apply_method_to_cache(method) {[]}
|
|
182
187
|
end
|
|
183
188
|
elsif @ar_object.respond_to? [*method].first
|
|
184
|
-
apply_method_to_cache(method) { |cache_item|
|
|
185
|
-
cache_item.value.send(*method)}
|
|
189
|
+
apply_method_to_cache(method) { |cache_item| cache_item.value.send(*method) rescue nil } # rescue in case we are on a nil association
|
|
186
190
|
else
|
|
187
191
|
self
|
|
188
192
|
end
|
|
@@ -212,6 +216,7 @@ module ReactiveRecord
|
|
|
212
216
|
end
|
|
213
217
|
|
|
214
218
|
def self.load_from_json(tree, target = nil)
|
|
219
|
+
tree.delete("*all") if tree["*"]
|
|
215
220
|
tree.each do |method, value|
|
|
216
221
|
method = JSON.parse(method) rescue method
|
|
217
222
|
new_target = nil
|
|
@@ -220,7 +225,7 @@ module ReactiveRecord
|
|
|
220
225
|
elsif method == "*all"
|
|
221
226
|
target.replace value.collect { |id| target.proxy_association.klass.find(id) }
|
|
222
227
|
elsif method.is_a? Integer or method =~ /^[0-9]+$/
|
|
223
|
-
new_target = target.proxy_association.klass.find(method)
|
|
228
|
+
new_target = target.proxy_association.klass.find(method)
|
|
224
229
|
target << new_target
|
|
225
230
|
elsif method.is_a? Array
|
|
226
231
|
new_target = target.send *method
|
|
@@ -231,12 +236,7 @@ module ReactiveRecord
|
|
|
231
236
|
target.send "#{method}=", new_target
|
|
232
237
|
else
|
|
233
238
|
new_target = target.send *method
|
|
234
|
-
|
|
235
|
-
new_target = target.send "#{method}=", new_target
|
|
236
|
-
rescue Exception => e
|
|
237
|
-
message = "FAILED #{target}.#{method} not set to #{new_target}"
|
|
238
|
-
`console.error(message)`
|
|
239
|
-
end
|
|
239
|
+
(new_target = target.send "#{method}=", new_target) rescue nil # this can happen for example if you say TodoItems.all
|
|
240
240
|
end
|
|
241
241
|
load_from_json(value, new_target) if new_target
|
|
242
242
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reactive-record
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mitch VanDuyn
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-08-
|
|
11
|
+
date: 2015-08-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|