reactive-record 0.7.18 → 0.7.19
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/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
|