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 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