reactive-record 0.7.5 → 0.7.6
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/associations.rb +6 -1
- data/lib/reactive_record/active_record/class_methods.rb +11 -2
- data/lib/reactive_record/active_record/reactive_record/base.rb +5 -1
- data/lib/reactive_record/active_record/reactive_record/collection.rb +0 -4
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +5 -0
- data/lib/reactive_record/server_data_cache.rb +36 -21
- 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: 8548152ff489f1a0eb74a6eb0acbe08bcf94acb0
|
4
|
+
data.tar.gz: 2f6578db7396a607c8b3e61bea163fb55c5699c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daab93265cb69a09597a46ed12cafda5975abdba0ac6eddb82b74123448ced47ee3d39b889d9ad7fc28ddf85bc7999ff73db8fd69b7fe76b9ce540571b51132a
|
7
|
+
data.tar.gz: e5ea4f5e44394b9103636a3b0081b7671caea1b90ab8627a5ba9b66976bcaaab212819da3e56aa3739a7903ef5cc1b98ddfb5fbbb7c1904ab6d9693241bef628
|
@@ -24,13 +24,18 @@ module ActiveRecord
|
|
24
24
|
owner_class.reflect_on_all_associations << self
|
25
25
|
@owner_class = owner_class
|
26
26
|
@macro = macro
|
27
|
+
@options = options
|
27
28
|
@klass_name = options[:class_name] || (collection? && name.camelize.gsub(/s$/,"")) || name.camelize
|
29
|
+
if @klass_name < ActiveRecord::Base
|
30
|
+
@klass = @klass_name
|
31
|
+
@klass_name = @klass_name.name
|
32
|
+
end rescue nil
|
28
33
|
@association_foreign_key = options[:foreign_key] || (macro == :belongs_to && "#{name}_id") || "#{@owner_class.name.underscore}_id"
|
29
34
|
@attribute = name
|
30
35
|
end
|
31
36
|
|
32
37
|
def inverse_of
|
33
|
-
unless @inverse_of
|
38
|
+
unless @options[:through] or @inverse_of
|
34
39
|
inverse_association = klass.reflect_on_all_associations.detect { | association | association.association_foreign_key == @association_foreign_key }
|
35
40
|
raise "Association #{@owner_class}.#{attribute} (foreign_key: #{@association_foreign_key}) has no inverse in #{@klass_name}" unless inverse_association
|
36
41
|
@inverse_of = inverse_association.attribute
|
@@ -62,11 +62,20 @@ module ActiveRecord
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def scope(name, body)
|
65
|
-
singleton_class.send(:define_method, name)
|
65
|
+
singleton_class.send(:define_method, name) do
|
66
|
+
ReactiveRecord::Base.class_scopes(self)[name] ||= ReactiveRecord::Collection.new(self, nil, nil, self, name)
|
67
|
+
end
|
68
|
+
singleton_class.send(:define_method, "#{name}=") do |collection|
|
69
|
+
ReactiveRecord::Base.class_scopes(self)[name] = collection
|
70
|
+
end
|
66
71
|
end
|
67
72
|
|
68
73
|
def all
|
69
|
-
ReactiveRecord::Collection.new(self, nil, nil, self, "all")
|
74
|
+
ReactiveRecord::Base.class_scopes(self)[:all] ||= ReactiveRecord::Collection.new(self, nil, nil, self, "all")
|
75
|
+
end
|
76
|
+
|
77
|
+
def all=(collection)
|
78
|
+
ReactiveRecord::Base.class_scopes(self)[:all] = collection
|
70
79
|
end
|
71
80
|
|
72
81
|
[:belongs_to, :has_many, :has_one].each do |macro|
|
@@ -48,6 +48,10 @@ module ReactiveRecord
|
|
48
48
|
ServerDataCache.load_from_json(json, target)
|
49
49
|
@data_loading = false
|
50
50
|
end
|
51
|
+
|
52
|
+
def self.class_scopes(model)
|
53
|
+
@class_scopes[model.base_class]
|
54
|
+
end
|
51
55
|
|
52
56
|
def self.find(model, attribute, value)
|
53
57
|
# will return the unique record with this attribute-value pair
|
@@ -165,7 +169,7 @@ module ReactiveRecord
|
|
165
169
|
attributes[attribute].attributes[inverse_of] = nil if attributes[attribute]
|
166
170
|
value.attributes[inverse_of] = @ar_instance
|
167
171
|
React::State.set_state(value.instance_variable_get(:@backing_record), inverse_of, @ar_instance) unless data_loading?
|
168
|
-
|
172
|
+
elsif attributes[attribute]
|
169
173
|
attributes[attribute].attributes[inverse_of] = nil
|
170
174
|
end
|
171
175
|
end
|
@@ -3,10 +3,6 @@ module ReactiveRecord
|
|
3
3
|
class Collection
|
4
4
|
|
5
5
|
def initialize(target_klass, owner = nil, association = nil, *vector)
|
6
|
-
if association and (association.macro != :has_many or association.klass != target_klass)
|
7
|
-
message = "unimplemented association #{owner} :#{association.macro} #{association.attribute}"
|
8
|
-
`console.error(#{message})`
|
9
|
-
end
|
10
6
|
@owner = owner # can be nil if this is an outer most scope
|
11
7
|
@association = association
|
12
8
|
@target_klass = target_klass
|
@@ -11,6 +11,7 @@ module ReactiveRecord
|
|
11
11
|
@server_data_cache = ReactiveRecord::ServerDataCache.new
|
12
12
|
else
|
13
13
|
@records = Hash.new { |hash, key| hash[key] = [] }
|
14
|
+
@class_scopes = Hash.new { |hash, key| hash[key] = {} }
|
14
15
|
if on_opal_client?
|
15
16
|
@pending_fetches = []
|
16
17
|
@last_fetch_at = Time.now
|
@@ -152,12 +153,16 @@ module ReactiveRecord
|
|
152
153
|
last_fetch_at = @last_fetch_at
|
153
154
|
pending_fetches = @pending_fetches.uniq
|
154
155
|
log(["Server Fetching: %o", pending_fetches.to_n])
|
156
|
+
start_time = Time.now
|
155
157
|
HTTP.post(`window.ReactiveRecordEnginePath`, payload: {pending_fetches: pending_fetches}).then do |response|
|
158
|
+
fetch_time = Time.now
|
159
|
+
log(" Fetched in: #{(fetch_time-start_time).to_i}s")
|
156
160
|
begin
|
157
161
|
ReactiveRecord::Base.load_from_json(response.json)
|
158
162
|
rescue Exception => e
|
159
163
|
log("Exception raised while loading json from server: #{e}", :error)
|
160
164
|
end
|
165
|
+
log(" Processed in: #{(Time.now-fetch_time).to_i}s")
|
161
166
|
log([" Returned: %o", response.json.to_n])
|
162
167
|
ReactiveRecord.run_blocks_to_load
|
163
168
|
ReactiveRecord::WhileLoading.loaded_at last_fetch_at
|
@@ -95,9 +95,10 @@ module ReactiveRecord
|
|
95
95
|
if RUBY_ENGINE != 'opal'
|
96
96
|
|
97
97
|
def [](*vector)
|
98
|
-
|
98
|
+
root = CacheItem.new(@cache, vector[0])
|
99
|
+
vector[1..-1].inject(root) { |cache_item, method| cache_item.apply_method method if cache_item }
|
99
100
|
vector[0] = vector[0].constantize
|
100
|
-
new_items = @cache.select { | cache_item | cache_item.
|
101
|
+
new_items = @cache.select { | cache_item | cache_item.root == root}
|
101
102
|
@requested_cache_items += new_items
|
102
103
|
new_items.last.value if new_items.last
|
103
104
|
end
|
@@ -128,6 +129,7 @@ module ReactiveRecord
|
|
128
129
|
|
129
130
|
attr_reader :vector
|
130
131
|
attr_reader :record_chain
|
132
|
+
attr_reader :root
|
131
133
|
|
132
134
|
def value
|
133
135
|
@ar_object
|
@@ -138,7 +140,10 @@ module ReactiveRecord
|
|
138
140
|
end
|
139
141
|
|
140
142
|
def self.new(db_cache, klass)
|
141
|
-
|
143
|
+
klass_constant = klass.constantize
|
144
|
+
if existing = db_cache.detect { |cached_item| cached_item.vector == [klass_constant] }
|
145
|
+
return existing
|
146
|
+
end
|
142
147
|
super
|
143
148
|
end
|
144
149
|
|
@@ -149,18 +154,25 @@ module ReactiveRecord
|
|
149
154
|
@ar_object = klass
|
150
155
|
@record_chain = []
|
151
156
|
@parent = nil
|
157
|
+
@root = self
|
152
158
|
db_cache << self
|
153
159
|
end
|
154
160
|
|
155
161
|
def apply_method_to_cache(method, &block)
|
156
162
|
@db_cache.inject(nil) do | representative, cache_item |
|
157
163
|
if cache_item.vector == vector
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
+
begin
|
165
|
+
new_ar_object = yield cache_item
|
166
|
+
cache_item.clone.instance_eval do
|
167
|
+
@vector = @vector + [method] # don't push it on since you need a new vector!
|
168
|
+
@ar_object = new_ar_object
|
169
|
+
@db_cache << self
|
170
|
+
@parent = cache_item
|
171
|
+
@root = cache_item.root
|
172
|
+
self
|
173
|
+
end
|
174
|
+
rescue
|
175
|
+
representative
|
164
176
|
end
|
165
177
|
else
|
166
178
|
representative
|
@@ -185,10 +197,13 @@ module ReactiveRecord
|
|
185
197
|
else
|
186
198
|
apply_method_to_cache(method) {[]}
|
187
199
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
200
|
+
else # @ar_object.respond_to? [*method].first
|
201
|
+
puts "apply #{method} to #{@vector}"
|
202
|
+
r = apply_method_to_cache(method) { |cache_item| cache_item.value.send(*method) }# rescue nil } # rescue in case we are on a nil association
|
203
|
+
puts "representative method = #{r}"
|
204
|
+
r
|
205
|
+
#else
|
206
|
+
# self
|
192
207
|
end
|
193
208
|
end
|
194
209
|
|
@@ -196,7 +211,7 @@ module ReactiveRecord
|
|
196
211
|
if @parent
|
197
212
|
if method == "*"
|
198
213
|
@parent.as_hash({@ar_object.id => children})
|
199
|
-
elsif @ar_object.class < ActiveRecord::Base
|
214
|
+
elsif @ar_object.class < ActiveRecord::Base and children.is_a? Hash
|
200
215
|
@parent.as_hash({method => children.merge({
|
201
216
|
:id => [@ar_object.id],
|
202
217
|
@ar_object.class.inheritance_column => [@ar_object[@ar_object.class.inheritance_column]],
|
@@ -216,31 +231,31 @@ module ReactiveRecord
|
|
216
231
|
end
|
217
232
|
|
218
233
|
def self.load_from_json(tree, target = nil)
|
219
|
-
|
234
|
+
ignore_all = nil
|
220
235
|
tree.each do |method, value|
|
221
236
|
method = JSON.parse(method) rescue method
|
222
237
|
new_target = nil
|
223
238
|
if !target
|
224
239
|
load_from_json(value, Object.const_get(method))
|
225
240
|
elsif method == "*all"
|
226
|
-
target.replace value.collect { |id| target.proxy_association.klass.find(id) }
|
241
|
+
target.replace value.collect { |id| target.proxy_association.klass.find(id) } unless ignore_all
|
227
242
|
elsif method.is_a? Integer or method =~ /^[0-9]+$/
|
228
|
-
|
229
|
-
target << new_target
|
243
|
+
ignore_all = true
|
244
|
+
target << (new_target = target.proxy_association.klass.find(method))
|
230
245
|
elsif method.is_a? Array
|
231
|
-
new_target = target.send *method
|
246
|
+
new_target = target.send *method unless value.is_a? Array # value is an array if scope returns nil
|
232
247
|
elsif value.is_a? Array
|
233
248
|
target.send "#{method}=", value.first
|
234
249
|
elsif value.is_a? Hash and value[:id] and value[:id].first
|
235
250
|
new_target = target.class.reflect_on_association(method).klass.find(value[:id].first)
|
236
251
|
target.send "#{method}=", new_target
|
237
252
|
else
|
238
|
-
new_target = target.send
|
239
|
-
(new_target = target.send "#{method}=", new_target) rescue nil # this can happen for example if you say TodoItems.all
|
253
|
+
new_target = target.send("#{method}=", target.send(method))
|
240
254
|
end
|
241
255
|
load_from_json(value, new_target) if new_target
|
242
256
|
end
|
243
257
|
target.save if target.respond_to? :save
|
258
|
+
|
244
259
|
end
|
245
260
|
|
246
261
|
|
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.6
|
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-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|