reactive-record 0.7.18 → 0.7.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/reactive_record/active_record/aggregations.rb +6 -1
- data/lib/reactive_record/active_record/class_methods.rb +12 -3
- data/lib/reactive_record/active_record/instance_methods.rb +5 -1
- data/lib/reactive_record/active_record/reactive_record/base.rb +11 -8
- data/lib/reactive_record/active_record/reactive_record/collection.rb +6 -6
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +13 -9
- data/lib/reactive_record/active_record/reactive_record/while_loading.rb +83 -64
- data/lib/reactive_record/server_data_cache.rb +22 -7
- 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: 7dec62330066fcb6cd84f0de9fc581b8dadde082
|
4
|
+
data.tar.gz: 9253a7995a08e7ff5c066d834768c22ed84e718c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c538da9a135037d64fccdd1137b17db4ddc1b1f4a288662389c0b491c6e8b1c110fcb211185f5607840c5484bc9922cc0a2b638658d53a9b84e753c53638a511
|
7
|
+
data.tar.gz: 8ce68f8a2c4c2eea795e96605b02cd941404e4cc1add15fd7aa11a8220b786d978f7c4e64d763e965f6bdb4bcffdc73c704b8543c4aadbbce69322b5b11bc9a7
|
@@ -25,7 +25,12 @@ module ActiveRecord
|
|
25
25
|
@owner_class = owner_class
|
26
26
|
@klass_name = options[:class_name] || name.camelize
|
27
27
|
@attribute = name
|
28
|
-
|
28
|
+
if options[:mapping].respond_to? :collect
|
29
|
+
@mapped_attributes = options[:mapping].collect &:last
|
30
|
+
else
|
31
|
+
ReactiveRecord::Base.log("improper aggregate definition #{@owner_class}, :#{name}, class_name: #{@klass_name} - missing mapping", :error)
|
32
|
+
@mapped_attributes = []
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
def klass
|
@@ -62,8 +62,9 @@ module ActiveRecord
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def scope(name, body)
|
65
|
-
singleton_class.send(:define_method, name) do
|
66
|
-
|
65
|
+
singleton_class.send(:define_method, name) do | *args |
|
66
|
+
args = args.count == 0 ? name : [name, *args]
|
67
|
+
ReactiveRecord::Base.class_scopes(self)[name] ||= ReactiveRecord::Collection.new(self, nil, nil, self, args)
|
67
68
|
end
|
68
69
|
singleton_class.send(:define_method, "#{name}=") do |collection|
|
69
70
|
ReactiveRecord::Base.class_scopes(self)[name] = collection
|
@@ -105,9 +106,12 @@ module ActiveRecord
|
|
105
106
|
|
106
107
|
def _react_param_conversion(param, opt = nil)
|
107
108
|
# defines how react will convert incoming json to this ActiveRecord model
|
109
|
+
times = {start: Time.now.to_f, json_start: 0, json_end: 0, db_load_start: 0, db_load_end: 0}
|
108
110
|
param_is_native = !param.respond_to?(:is_a?) rescue true
|
111
|
+
times[:json_start] = Time.now.to_f
|
109
112
|
param = JSON.from_object param if param_is_native
|
110
|
-
|
113
|
+
times[:json_end] = Time.now.to_f
|
114
|
+
result = if param.is_a? self
|
111
115
|
param
|
112
116
|
elsif param.is_a? Hash
|
113
117
|
if opt == :validate_only
|
@@ -119,12 +123,17 @@ module ActiveRecord
|
|
119
123
|
else
|
120
124
|
target = new
|
121
125
|
end
|
126
|
+
times[:db_load_start] = Time.now.to_f
|
122
127
|
ReactiveRecord::Base.load_from_json(Hash[param.collect { |key, value| [key, [value]] }], target)
|
128
|
+
times[:db_load_end] = Time.now.to_f
|
123
129
|
target
|
124
130
|
end
|
125
131
|
else
|
126
132
|
nil
|
127
133
|
end
|
134
|
+
times[:end] = Time.now.to_f
|
135
|
+
#puts "times - total: #{'%.04f' % (times[:end]-times[:start])}, native conversion: #{'%.04f' % (times[:json_end]-times[:json_start])}, loading: #{'%.04f' % (times[:db_load_end]-times[:db_load_start])}"
|
136
|
+
result
|
128
137
|
end
|
129
138
|
|
130
139
|
end
|
@@ -2,6 +2,8 @@ module ActiveRecord
|
|
2
2
|
|
3
3
|
module InstanceMethods
|
4
4
|
|
5
|
+
attr_reader :backing_record
|
6
|
+
|
5
7
|
def attributes
|
6
8
|
@backing_record.attributes
|
7
9
|
end
|
@@ -68,13 +70,15 @@ module ActiveRecord
|
|
68
70
|
@backing_record.reactive_set!(attribute_name, args[0])
|
69
71
|
elsif args.count == 0 && !block
|
70
72
|
@backing_record.reactive_get!(name)
|
73
|
+
elsif !block
|
74
|
+
@backing_record.reactive_get!([[name]+args])
|
71
75
|
else
|
72
76
|
super
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
76
80
|
def save(opts = {}, &block)
|
77
|
-
@backing_record.save(opts.has_key?(:validate) ? opts[:validate] : true, &block)
|
81
|
+
@backing_record.save(opts.has_key?(:validate) ? opts[:validate] : true, opts[:force], &block)
|
78
82
|
end
|
79
83
|
|
80
84
|
def saving?
|
@@ -49,6 +49,7 @@ module ReactiveRecord
|
|
49
49
|
def self.load_data(&block)
|
50
50
|
current_data_loading, @data_loading = [@data_loading, true]
|
51
51
|
yield
|
52
|
+
ensure
|
52
53
|
@data_loading = current_data_loading
|
53
54
|
end
|
54
55
|
|
@@ -143,7 +144,7 @@ module ReactiveRecord
|
|
143
144
|
if !(value and existing_record = records[@model].detect { |record| record.attributes[primary_key] == value})
|
144
145
|
attributes[primary_key] = value
|
145
146
|
else
|
146
|
-
@ar_instance.
|
147
|
+
@ar_instance.instance_variable_set(:@backing_record, existing_record)
|
147
148
|
existing_record.attributes.merge!(attributes) { |key, v1, v2| v1 }
|
148
149
|
end
|
149
150
|
end
|
@@ -183,7 +184,7 @@ module ReactiveRecord
|
|
183
184
|
elsif value
|
184
185
|
attributes[attribute].attributes[inverse_of] = nil if attributes[attribute]
|
185
186
|
value.attributes[inverse_of] = @ar_instance
|
186
|
-
React::State.set_state(value.
|
187
|
+
React::State.set_state(value.backing_record, inverse_of, @ar_instance) unless data_loading?
|
187
188
|
elsif attributes[attribute]
|
188
189
|
attributes[attribute].attributes[inverse_of] = nil
|
189
190
|
end
|
@@ -194,10 +195,10 @@ module ReactiveRecord
|
|
194
195
|
raise "unitialized aggregate attribute - should never happen"
|
195
196
|
end
|
196
197
|
|
197
|
-
aggregate_record = attributes[attribute].
|
198
|
+
aggregate_record = attributes[attribute].backing_record
|
198
199
|
|
199
200
|
if value
|
200
|
-
value_attributes = value.
|
201
|
+
value_attributes = value.backing_record.attributes
|
201
202
|
aggregation.mapped_attributes.each { |mapped_attribute| aggregate_record.update_attribute(mapped_attribute, value_attributes[mapped_attribute])}
|
202
203
|
else
|
203
204
|
aggregation.mapped_attributes.each { |mapped_attribute| aggregate_record.update_attribute(mapped_attribute, nil) }
|
@@ -217,7 +218,7 @@ module ReactiveRecord
|
|
217
218
|
if association = @model.reflect_on_association(attribute) and association.collection?
|
218
219
|
attributes[attribute] != @synced_attributes[attribute]
|
219
220
|
else
|
220
|
-
!attributes[attribute].
|
221
|
+
!attributes[attribute].backing_record.changed_attributes.empty?
|
221
222
|
end
|
222
223
|
elsif association = @model.reflect_on_association(attribute) and association.collection?
|
223
224
|
value != @synced_attributes[attribute]
|
@@ -259,7 +260,9 @@ module ReactiveRecord
|
|
259
260
|
if value.is_a? Collection
|
260
261
|
@synced_attributes[key] = value.dup_for_sync
|
261
262
|
elsif aggregation = model.reflect_on_aggregation(key)
|
262
|
-
value.
|
263
|
+
value.backing_record.sync!
|
264
|
+
else
|
265
|
+
@synced_attributes[key] = JSON.parse(value.to_json)
|
263
266
|
end
|
264
267
|
end
|
265
268
|
@changed_attributes = []
|
@@ -322,7 +325,7 @@ module ReactiveRecord
|
|
322
325
|
else
|
323
326
|
new_from_vector(association.klass, nil, *vector, association.attribute)
|
324
327
|
end
|
325
|
-
instance_backing_record_attributes = instance.
|
328
|
+
instance_backing_record_attributes = instance.backing_record.attributes
|
326
329
|
inverse_association = association.klass.reflect_on_association(inverse_of)
|
327
330
|
if inverse_association.collection?
|
328
331
|
instance_backing_record_attributes[inverse_of] = if id and id != ""
|
@@ -360,7 +363,7 @@ module ReactiveRecord
|
|
360
363
|
@attributes[method] = Collection.new(association.klass, @ar_instance, association)
|
361
364
|
elsif aggregation = @model.reflect_on_aggregation(method)
|
362
365
|
@attributes[method] = aggregation.klass.new.tap do |aggregate|
|
363
|
-
backing_record = aggregate.
|
366
|
+
backing_record = aggregate.backing_record
|
364
367
|
backing_record.aggregate_owner = self
|
365
368
|
backing_record.aggregate_attribute = method
|
366
369
|
end
|
@@ -11,7 +11,7 @@ module ReactiveRecord
|
|
11
11
|
elsif vector.length > 0
|
12
12
|
@vector = vector
|
13
13
|
elsif owner
|
14
|
-
@vector = owner.
|
14
|
+
@vector = owner.backing_record.vector + [association.attribute]
|
15
15
|
else
|
16
16
|
@vector = [target_klass]
|
17
17
|
end
|
@@ -37,7 +37,7 @@ module ReactiveRecord
|
|
37
37
|
else
|
38
38
|
@dummy_collection = ReactiveRecord::Base.load_from_db(*@vector, "*all")
|
39
39
|
@dummy_record = ReactiveRecord::Base.new_from_vector(@target_klass, nil, *@vector, "*")
|
40
|
-
@dummy_record.
|
40
|
+
@dummy_record.backing_record.attributes[@association.inverse_of] = @owner if @association and @association.inverse_of
|
41
41
|
@collection << @dummy_record
|
42
42
|
end
|
43
43
|
end
|
@@ -67,7 +67,7 @@ module ReactiveRecord
|
|
67
67
|
|
68
68
|
|
69
69
|
def <<(item)
|
70
|
-
backing_record = item.
|
70
|
+
backing_record = item.backing_record
|
71
71
|
# if backing_record and @owner and @association and inverse_of = @association.inverse_of
|
72
72
|
# item.attributes[inverse_of].attributes[@association.attribute].delete(item) if item.attributes[inverse_of] and item.attributes[inverse_of].attributes[@association.attribute]
|
73
73
|
# item.attributes[inverse_of] = @owner
|
@@ -79,7 +79,7 @@ module ReactiveRecord
|
|
79
79
|
current_association = item.attributes[inverse_of]
|
80
80
|
backing_record.update_attribute(inverse_of, @owner)
|
81
81
|
current_association.attributes[@association.attribute].delete(item) if current_association and current_association.attributes[@association.attribute]
|
82
|
-
@owner.
|
82
|
+
@owner.backing_record.update_attribute(@association.attribute) # forces a check if association contents have changed from synced values
|
83
83
|
end
|
84
84
|
@collection.delete(@dummy_record)
|
85
85
|
@dummy_record = @dummy_collection = nil
|
@@ -114,11 +114,11 @@ module ReactiveRecord
|
|
114
114
|
|
115
115
|
def delete(item)
|
116
116
|
if @owner and @association and inverse_of = @association.inverse_of
|
117
|
-
if backing_record = item.
|
117
|
+
if backing_record = item.backing_record and backing_record.attributes[inverse_of] == @owner
|
118
118
|
# the if prevents double update if delete is being called from << (see << above)
|
119
119
|
backing_record.update_attribute(inverse_of, nil)
|
120
120
|
end
|
121
|
-
all.delete(item).tap { @owner.
|
121
|
+
all.delete(item).tap { @owner.backing_record.update_attribute(@association.attribute) } # forces a check if association contents have changed from synced values
|
122
122
|
else
|
123
123
|
all.delete(item)
|
124
124
|
end
|
@@ -90,8 +90,8 @@ module ReactiveRecord
|
|
90
90
|
|
91
91
|
def notify
|
92
92
|
unless ReactiveRecord::Base.data_loading?
|
93
|
-
ReactiveRecord.loads_pending!
|
94
|
-
ReactiveRecord::WhileLoading.loading!
|
93
|
+
ReactiveRecord.loads_pending! #loads
|
94
|
+
ReactiveRecord::WhileLoading.loading! #loads
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
@@ -140,6 +140,7 @@ module ReactiveRecord
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def to_date
|
143
|
+
notify
|
143
144
|
"2001-01-01T00:00:00.000-00:00".to_date
|
144
145
|
end
|
145
146
|
|
@@ -151,7 +152,9 @@ module ReactiveRecord
|
|
151
152
|
|
152
153
|
|
153
154
|
def self.schedule_fetch
|
154
|
-
|
155
|
+
#ReactiveRecord.loads_pending!
|
156
|
+
#ReactiveRecord::WhileLoading.loading!
|
157
|
+
@fetch_scheduled ||= after(0.01) do
|
155
158
|
if @pending_fetches.count > 0 # during testing we might reset the context while there are pending fetches
|
156
159
|
last_fetch_at = @last_fetch_at
|
157
160
|
pending_fetches = @pending_fetches.uniq
|
@@ -169,6 +172,7 @@ module ReactiveRecord
|
|
169
172
|
log([" Returned: %o", response.json.to_n])
|
170
173
|
ReactiveRecord.run_blocks_to_load
|
171
174
|
ReactiveRecord::WhileLoading.loaded_at last_fetch_at
|
175
|
+
ReactiveRecord::WhileLoading.quiet! if @pending_fetches.empty?
|
172
176
|
end.fail do |response|
|
173
177
|
log("Fetch failed", :error)
|
174
178
|
ReactiveRecord.run_blocks_to_load(response.body)
|
@@ -188,13 +192,13 @@ module ReactiveRecord
|
|
188
192
|
|
189
193
|
if RUBY_ENGINE == 'opal'
|
190
194
|
|
191
|
-
def save(validate, &block)
|
195
|
+
def save(validate, force, &block)
|
192
196
|
|
193
197
|
if data_loading?
|
194
198
|
|
195
199
|
sync!
|
196
200
|
|
197
|
-
elsif changed?
|
201
|
+
elsif force or changed?
|
198
202
|
|
199
203
|
# we want to pass not just the model data to save, but also enough information so that on return from the server
|
200
204
|
# we can update the models on the client
|
@@ -223,18 +227,18 @@ module ReactiveRecord
|
|
223
227
|
record.attributes.each do |attribute, value|
|
224
228
|
if association = record.model.reflect_on_association(attribute)
|
225
229
|
if association.collection?
|
226
|
-
value.each { |assoc| add_new_association.call record, attribute, assoc.
|
230
|
+
value.each { |assoc| add_new_association.call record, attribute, assoc.backing_record }
|
227
231
|
elsif value
|
228
|
-
add_new_association.call record, attribute, value.
|
232
|
+
add_new_association.call record, attribute, value.backing_record
|
229
233
|
else
|
230
234
|
output_attributes[attribute] = nil
|
231
235
|
end
|
232
236
|
elsif record.model.reflect_on_aggregation(attribute)
|
233
|
-
add_new_association.call record, attribute, value.
|
237
|
+
add_new_association.call record, attribute, value.backing_record
|
234
238
|
elsif record.changed?(attribute)
|
235
239
|
output_attributes[attribute] = value
|
236
240
|
end
|
237
|
-
end if record.changed?
|
241
|
+
end if record.changed? || (record == self && force)
|
238
242
|
record_index += 1
|
239
243
|
end
|
240
244
|
|
@@ -17,6 +17,8 @@ module ReactiveRecord
|
|
17
17
|
end
|
18
18
|
@loads_pending = @load_stack.pop
|
19
19
|
promise
|
20
|
+
rescue Exception => e
|
21
|
+
log "ReactiveRecord.load exception raised during retry: #{e}", :error
|
20
22
|
end
|
21
23
|
|
22
24
|
def self.loads_pending!
|
@@ -27,7 +29,9 @@ module ReactiveRecord
|
|
27
29
|
if @blocks_to_load
|
28
30
|
blocks_to_load = @blocks_to_load
|
29
31
|
@blocks_to_load = []
|
32
|
+
@load_stack ||= []
|
30
33
|
blocks_to_load.each do |promise_and_block|
|
34
|
+
@load_stack << @loads_pending
|
31
35
|
@loads_pending = nil
|
32
36
|
result = promise_and_block.last.call(failure)
|
33
37
|
if @loads_pending and !failure
|
@@ -35,65 +39,66 @@ module ReactiveRecord
|
|
35
39
|
else
|
36
40
|
promise_and_block.first.resolve result
|
37
41
|
end
|
42
|
+
@loads_pending = @load_stack.pop
|
38
43
|
end
|
39
44
|
end
|
40
45
|
rescue Exception => e
|
41
|
-
|
42
|
-
`console.error(#{message})`
|
46
|
+
log "ReactiveRecord.load exception raised during retry: #{e}", :error
|
43
47
|
end
|
44
48
|
|
45
|
-
|
49
|
+
|
46
50
|
# Adds while_loading feature to React
|
47
51
|
# to use attach a .while_loading handler to any element for example
|
48
52
|
# div { "displayed if everything is loaded" }.while_loading { "displayed while I'm loading" }
|
49
53
|
# the contents of the div will be switched (using jQuery.show/hide) depending on the state of contents of the first block
|
50
|
-
|
54
|
+
|
51
55
|
# To notify React that something is loading use React::WhileLoading.loading!
|
52
56
|
# once everything is loaded then do React::WhileLoading.loaded_at message (typically a time stamp just for debug purposes)
|
53
|
-
|
57
|
+
|
54
58
|
class WhileLoading
|
55
|
-
|
59
|
+
|
56
60
|
include React::IsomorphicHelpers
|
57
|
-
|
58
|
-
before_first_mount do
|
61
|
+
|
62
|
+
before_first_mount do
|
59
63
|
@css_to_preload = ""
|
60
64
|
@while_loading_counter = 0
|
61
65
|
end
|
62
|
-
|
66
|
+
|
63
67
|
def get_next_while_loading_counter
|
64
68
|
@while_loading_counter += 1
|
65
69
|
end
|
66
|
-
|
70
|
+
|
67
71
|
def preload_css(css)
|
68
72
|
@css_to_preload << css << "\n"
|
69
73
|
end
|
70
|
-
|
74
|
+
|
71
75
|
prerender_footer do
|
72
76
|
"<style>\n#{@css_to_preload}\n</style>".tap { @css_to_preload = ""}
|
73
77
|
end
|
74
|
-
|
78
|
+
|
75
79
|
if RUBY_ENGINE == 'opal'
|
76
|
-
|
80
|
+
|
77
81
|
# I DONT THINK WE USE opal-jquery in this module anymore - require 'opal-jquery' if opal_client?
|
78
|
-
|
82
|
+
|
79
83
|
include React::Component
|
80
|
-
|
84
|
+
|
81
85
|
required_param :loading
|
82
86
|
required_param :loaded_children
|
83
87
|
required_param :loading_children
|
84
88
|
required_param :element_type
|
85
89
|
required_param :element_props
|
86
90
|
optional_param :display, default: ""
|
87
|
-
|
91
|
+
|
88
92
|
class << self
|
89
|
-
|
93
|
+
|
90
94
|
def loading?
|
91
95
|
@is_loading
|
92
96
|
end
|
93
|
-
|
97
|
+
|
94
98
|
def loading!
|
95
99
|
React::RenderingContext.waiting_on_resources = true
|
96
100
|
React::State.get_state(self, :loaded_at)
|
101
|
+
React::State.set_state(self, :quiet, false)
|
97
102
|
@is_loading = true
|
98
103
|
end
|
99
104
|
|
@@ -101,27 +106,41 @@ module ReactiveRecord
|
|
101
106
|
React::State.set_state(self, :loaded_at, loaded_at)
|
102
107
|
@is_loading = false
|
103
108
|
end
|
104
|
-
|
109
|
+
|
110
|
+
def quiet?
|
111
|
+
React::State.get_state(self, :quiet)
|
112
|
+
end
|
113
|
+
|
114
|
+
def page_loaded?
|
115
|
+
React::State.get_state(self, :page_loaded)
|
116
|
+
end
|
117
|
+
|
118
|
+
def quiet!
|
119
|
+
React::State.set_state(self, :quiet, true)
|
120
|
+
after(1) { React::State.set_state(self, :page_loaded, true) } unless on_opal_server? or @page_loaded
|
121
|
+
@page_loaded = true
|
122
|
+
end
|
123
|
+
|
105
124
|
def add_style_sheet
|
106
125
|
@style_sheet ||= %x{
|
107
126
|
$('<style type="text/css">'+
|
108
127
|
' .reactive_record_is_loading > .reactive_record_show_when_loaded { display: none; }'+
|
109
128
|
' .reactive_record_is_loaded > .reactive_record_show_while_loading { display: none; }'+
|
110
|
-
'</style>').appendTo("head")
|
111
|
-
}
|
129
|
+
'</style>').appendTo("head")
|
130
|
+
}
|
112
131
|
end
|
113
|
-
|
132
|
+
|
114
133
|
end
|
115
|
-
|
134
|
+
|
116
135
|
before_mount do
|
117
136
|
@uniq_id = WhileLoading.get_next_while_loading_counter
|
118
137
|
WhileLoading.preload_css(
|
119
138
|
".reactive_record_while_loading_container_#{@uniq_id} > :nth-child(1n+#{loaded_children.count+1}) {\n"+
|
120
|
-
" display: none;\n"+
|
139
|
+
" display: none;\n"+
|
121
140
|
"}\n"
|
122
141
|
)
|
123
142
|
end
|
124
|
-
|
143
|
+
|
125
144
|
after_mount do
|
126
145
|
@waiting_on_resources = loading
|
127
146
|
WhileLoading.add_style_sheet
|
@@ -131,11 +150,11 @@ module ReactiveRecord
|
|
131
150
|
$(node).children(':nth-child(1n+'+#{loaded_children.count+1}+')').addClass('reactive_record_show_while_loading');
|
132
151
|
}
|
133
152
|
end
|
134
|
-
|
153
|
+
|
135
154
|
after_update do
|
136
155
|
@waiting_on_resources = loading
|
137
156
|
end
|
138
|
-
|
157
|
+
|
139
158
|
def render
|
140
159
|
props = element_props.dup
|
141
160
|
classes = [props[:class], props[:className], "reactive_record_while_loading_container_#{@uniq_id}"].compact.join(" ")
|
@@ -146,64 +165,64 @@ module ReactiveRecord
|
|
146
165
|
})
|
147
166
|
React.create_element(element_type, props) { loaded_children + loading_children }
|
148
167
|
end
|
149
|
-
|
168
|
+
|
150
169
|
end
|
151
|
-
|
170
|
+
|
152
171
|
end
|
153
|
-
|
172
|
+
|
154
173
|
end
|
155
|
-
|
174
|
+
|
156
175
|
module React
|
157
|
-
|
176
|
+
|
158
177
|
class Element
|
159
|
-
|
178
|
+
|
160
179
|
def while_loading(display = "", &loading_display_block)
|
161
|
-
|
180
|
+
|
162
181
|
loaded_children = []
|
163
182
|
loaded_children = block.call.dup if block
|
164
|
-
|
183
|
+
|
165
184
|
loading_children = [display]
|
166
185
|
loading_children = RenderingContext.build do |buffer|
|
167
186
|
result = loading_display_block.call
|
168
187
|
buffer << result.to_s if result.is_a? String
|
169
188
|
buffer.dup
|
170
|
-
end if loading_display_block
|
189
|
+
end if loading_display_block
|
171
190
|
RenderingContext.replace(
|
172
191
|
self,
|
173
192
|
React.create_element(
|
174
|
-
ReactiveRecord::WhileLoading,
|
175
|
-
loading: waiting_on_resources,
|
176
|
-
loading_children: loading_children,
|
177
|
-
loaded_children: loaded_children,
|
178
|
-
element_type: type,
|
179
|
-
element_props: properties)
|
193
|
+
ReactiveRecord::WhileLoading,
|
194
|
+
loading: waiting_on_resources,
|
195
|
+
loading_children: loading_children,
|
196
|
+
loaded_children: loaded_children,
|
197
|
+
element_type: type,
|
198
|
+
element_props: properties)
|
180
199
|
)
|
181
200
|
end
|
182
|
-
|
201
|
+
|
183
202
|
def hide_while_loading
|
184
203
|
while_loading
|
185
204
|
end
|
186
|
-
|
205
|
+
|
187
206
|
end
|
188
|
-
|
207
|
+
|
189
208
|
module Component
|
190
|
-
|
209
|
+
|
191
210
|
alias_method :original_component_did_mount, :component_did_mount
|
192
|
-
|
211
|
+
|
193
212
|
def component_did_mount(*args)
|
194
213
|
original_component_did_mount(*args)
|
195
214
|
reactive_record_link_to_enclosing_while_loading_container
|
196
215
|
reactive_record_link_set_while_loading_container_class
|
197
216
|
end
|
198
|
-
|
217
|
+
|
199
218
|
alias_method :original_component_did_update, :component_did_update
|
200
|
-
|
219
|
+
|
201
220
|
def component_did_update(*args)
|
202
221
|
original_component_did_update(*args)
|
203
222
|
reactive_record_link_set_while_loading_container_class
|
204
223
|
end
|
205
|
-
|
206
|
-
def reactive_record_link_to_enclosing_while_loading_container
|
224
|
+
|
225
|
+
def reactive_record_link_to_enclosing_while_loading_container
|
207
226
|
# Call after any component mounts - attaches the containers loading id to this component
|
208
227
|
# Fyi, the while_loading container is responsible for setting its own link to itself
|
209
228
|
|
@@ -219,11 +238,11 @@ module React
|
|
219
238
|
}
|
220
239
|
|
221
240
|
end
|
222
|
-
|
241
|
+
|
223
242
|
def reactive_record_link_set_while_loading_container_class
|
224
|
-
|
243
|
+
|
225
244
|
%x{
|
226
|
-
|
245
|
+
|
227
246
|
var node = #{@native}.getDOMNode();
|
228
247
|
var while_loading_container_id = $(node).attr('data-reactive_record_enclosing_while_loading_container_id');
|
229
248
|
if (while_loading_container_id) {
|
@@ -234,12 +253,12 @@ module React
|
|
234
253
|
$(node).removeClass('reactive_record_is_loaded');
|
235
254
|
$(while_loading_container).addClass('reactive_record_is_loading');
|
236
255
|
$(while_loading_container).removeClass('reactive_record_is_loaded');
|
237
|
-
|
256
|
+
|
238
257
|
} else if (!$(node).hasClass('reactive_record_is_loaded')) {
|
239
|
-
|
258
|
+
|
240
259
|
if (!$(node).attr('data-reactive_record_while_loading_container_id')) {
|
241
260
|
$(node).removeClass('reactive_record_is_loading');
|
242
|
-
$(node).addClass('reactive_record_is_loaded');
|
261
|
+
$(node).addClass('reactive_record_is_loaded');
|
243
262
|
}
|
244
263
|
if (!$(while_loading_container).hasClass('reactive_record_is_loaded')) {
|
245
264
|
var loading_children = $(while_loading_container).
|
@@ -247,16 +266,16 @@ module React
|
|
247
266
|
if (loading_children.length == 0) {
|
248
267
|
$(while_loading_container).removeClass('reactive_record_is_loading')
|
249
268
|
$(while_loading_container).addClass('reactive_record_is_loaded')
|
250
|
-
}
|
269
|
+
}
|
251
270
|
}
|
252
|
-
|
271
|
+
|
253
272
|
}
|
254
|
-
|
273
|
+
|
255
274
|
}
|
256
|
-
}
|
257
|
-
|
275
|
+
}
|
276
|
+
|
258
277
|
end
|
259
|
-
|
278
|
+
|
260
279
|
end if RUBY_ENGINE == 'opal'
|
261
280
|
|
262
|
-
end
|
281
|
+
end
|
@@ -177,7 +177,8 @@ module ReactiveRecord
|
|
177
177
|
@root = cache_item.root
|
178
178
|
self
|
179
179
|
end
|
180
|
-
rescue
|
180
|
+
rescue Exception => e
|
181
|
+
raise "ReactiveRecord exception caught when applying #{method} to db objects #{e}" if cache_item.value and cache_item.value != []
|
181
182
|
representative
|
182
183
|
end
|
183
184
|
else
|
@@ -208,6 +209,13 @@ module ReactiveRecord
|
|
208
209
|
end
|
209
210
|
end
|
210
211
|
|
212
|
+
def jsonize(method)
|
213
|
+
# sadly standard json converts {[:foo, nil] => 123} to {"['foo', nil]": 123}
|
214
|
+
# luckily [:foo, nil] does convert correctly
|
215
|
+
# so we check the methods and force proper conversion
|
216
|
+
method.is_a?(Array) ? method.to_json : method
|
217
|
+
end
|
218
|
+
|
211
219
|
def as_hash(children = nil)
|
212
220
|
unless children
|
213
221
|
return {} if @ar_object.is_a?(Class) and (@ar_object < ActiveRecord::Base)
|
@@ -221,14 +229,14 @@ module ReactiveRecord
|
|
221
229
|
@parent.as_hash({@ar_object.id => children})
|
222
230
|
end
|
223
231
|
elsif @ar_object.class < ActiveRecord::Base and children.is_a? Hash
|
224
|
-
@parent.as_hash({method => children.merge({
|
232
|
+
@parent.as_hash({jsonize(method) => children.merge({
|
225
233
|
:id => [@ar_object.id],
|
226
234
|
@ar_object.class.inheritance_column => [@ar_object[@ar_object.class.inheritance_column]],
|
227
235
|
})})
|
228
236
|
elsif method == "*all"
|
229
|
-
@parent.as_hash({method => children.first})
|
237
|
+
@parent.as_hash({jsonize(method) => children.first})
|
230
238
|
else
|
231
|
-
@parent.as_hash({method => children})
|
239
|
+
@parent.as_hash({jsonize(method) => children})
|
232
240
|
end
|
233
241
|
else
|
234
242
|
{method.name => children}
|
@@ -258,14 +266,21 @@ module ReactiveRecord
|
|
258
266
|
ignore_all = true
|
259
267
|
target << (new_target = target.proxy_association.klass.find(method))
|
260
268
|
elsif method.is_a? Array
|
261
|
-
|
269
|
+
if !(target.class < ActiveRecord::Base)
|
270
|
+
new_target = target.send *method unless value.is_a? Array # value is an array if scope returns nil
|
271
|
+
else
|
272
|
+
target.attributes[[method]] = value.first
|
273
|
+
end
|
262
274
|
elsif value.is_a? Array
|
263
|
-
target.send "#{method}=", value.first
|
275
|
+
#target.send "#{method}=", value.first
|
276
|
+
target.backing_record.reactive_set!(method, value.first)
|
264
277
|
elsif value.is_a? Hash and value[:id] and value[:id].first #and
|
265
278
|
association = target.class.reflect_on_association(method)
|
266
279
|
new_target = association.klass.find(value[:id].first)
|
267
|
-
target.send "#{method}=", new_target
|
280
|
+
#target.send "#{method}=", new_target
|
281
|
+
target.backing_record.reactive_set!(method, new_target)
|
268
282
|
else
|
283
|
+
# target might be able to respond to method directly so we can't optimize out the target send
|
269
284
|
new_target = target.send("#{method}=", target.send(method))
|
270
285
|
end
|
271
286
|
load_from_json(value, new_target) if new_target
|
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.19
|
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-09-
|
11
|
+
date: 2015-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|