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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7767643d2625ad16929d2179c33f286d67f841cc
4
- data.tar.gz: 4f717b2c85e11fd7e8eaf793092000c944ba67b5
3
+ metadata.gz: 7dec62330066fcb6cd84f0de9fc581b8dadde082
4
+ data.tar.gz: 9253a7995a08e7ff5c066d834768c22ed84e718c
5
5
  SHA512:
6
- metadata.gz: 1537f31bcbed3cd4b14d254e4077c5de1fd1e9cba2b89548bd65b41877aa353913b8cab4e09e944dde038ac950a1b83a37253e2490df12b079bfff918198b01e
7
- data.tar.gz: 6f8beda7d146de1915604aca96f7ea8a35799ae7a990e5b436c60747bc50a4d80146ce2a5ef06bb3b0c9c070bc0a8f21d32c88295b19395a38e8cb5bbb22f5e8
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
- @mapped_attributes = options[:mapping].collect &:last
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
- ReactiveRecord::Base.class_scopes(self)[name] ||= ReactiveRecord::Collection.new(self, nil, nil, self, name)
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
- if param.is_a? self
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.instance_eval { @backing_record = existing_record }
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.instance_variable_get(:@backing_record), inverse_of, @ar_instance) unless data_loading?
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].instance_variable_get(:@backing_record)
198
+ aggregate_record = attributes[attribute].backing_record
198
199
 
199
200
  if value
200
- value_attributes = value.instance_variable_get(:@backing_record).attributes
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].instance_variable_get(:@backing_record).changed_attributes.empty?
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.instance_variable_get(:@backing_record).sync!
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.instance_variable_get(:@backing_record).attributes
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.instance_variable_get(:@backing_record)
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.instance_variable_get(:@backing_record).vector + [association.attribute]
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.instance_variable_get(:@backing_record).attributes[@association.inverse_of] = @owner if @association and @association.inverse_of
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.instance_variable_get(:@backing_record)
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.instance_variable_get(:@backing_record).update_attribute(@association.attribute) # forces a check if association contents have changed from synced values
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.instance_variable_get(:@backing_record) and backing_record.attributes[inverse_of] == @owner
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.instance_variable_get(:@backing_record).update_attribute(@association.attribute) } # forces a check if association contents have changed from synced values
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
- @fetch_scheduled ||= after(0.001) do
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.instance_variable_get(:@backing_record) }
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.instance_variable_get(:@backing_record)
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.instance_variable_get(:@backing_record)
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
- message = "ReactiveRecord.run_blocks_to_load exception raised: #{e}"
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
- new_target = target.send *method unless value.is_a? Array # value is an array if scope returns nil
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
@@ -1,3 +1,3 @@
1
1
  module ReactiveRecord
2
- VERSION = "0.7.18"
2
+ VERSION = "0.7.19"
3
3
  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.18
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-25 00:00:00.000000000 Z
11
+ date: 2015-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails