hyper-model 1.0.alpha1.4 → 1.0.alpha1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/active_record_base.rb +1 -1
- data/lib/hyper-model.rb +1 -0
- data/lib/hyper_model/version.rb +1 -1
- data/lib/hyper_react/input_tags.rb +2 -1
- data/lib/reactive_record/active_record/associations.rb +117 -32
- data/lib/reactive_record/active_record/class_methods.rb +68 -14
- data/lib/reactive_record/active_record/error.rb +2 -0
- data/lib/reactive_record/active_record/errors.rb +8 -4
- data/lib/reactive_record/active_record/instance_methods.rb +22 -1
- data/lib/reactive_record/active_record/reactive_record/backing_record_inspector.rb +4 -4
- data/lib/reactive_record/active_record/reactive_record/base.rb +16 -5
- data/lib/reactive_record/active_record/reactive_record/collection.rb +53 -29
- data/lib/reactive_record/active_record/reactive_record/dummy_polymorph.rb +22 -0
- data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +1 -0
- data/lib/reactive_record/active_record/reactive_record/getters.rb +19 -7
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +28 -11
- data/lib/reactive_record/active_record/reactive_record/lookup_tables.rb +5 -5
- data/lib/reactive_record/active_record/reactive_record/setters.rb +104 -66
- data/lib/reactive_record/broadcast.rb +19 -9
- data/lib/reactive_record/interval.rb +3 -3
- data/lib/reactive_record/scope_description.rb +3 -2
- data/lib/reactive_record/server_data_cache.rb +12 -3
- data/polymorph-notes.md +143 -0
- metadata +9 -7
@@ -4,11 +4,11 @@ module ReactiveRecord
|
|
4
4
|
# the appropriate string. The order of execution is important!
|
5
5
|
module BackingRecordInspector
|
6
6
|
def inspection_details
|
7
|
-
return error_details
|
8
|
-
return new_details
|
7
|
+
return error_details unless errors.empty?
|
8
|
+
return new_details if new?
|
9
9
|
return destroyed_details if destroyed
|
10
|
-
return loading_details
|
11
|
-
return dirty_details
|
10
|
+
return loading_details unless @attributes.key? primary_key
|
11
|
+
return dirty_details unless changed_attributes.empty?
|
12
12
|
"[loaded id: #{id}]"
|
13
13
|
end
|
14
14
|
|
@@ -71,7 +71,7 @@ module ReactiveRecord
|
|
71
71
|
if (id_to_find = attrs[model.primary_key])
|
72
72
|
!new_only && lookup_by_id(model, id_to_find)
|
73
73
|
else
|
74
|
-
@records[model].detect do |r|
|
74
|
+
@records[model.base_class].detect do |r|
|
75
75
|
(r.new? || !new_only) &&
|
76
76
|
!attrs.detect { |attr, value| r.synced_attributes[attr] != value }
|
77
77
|
end
|
@@ -118,6 +118,9 @@ module ReactiveRecord
|
|
118
118
|
# this is the equivilent of find but for associations and aggregations
|
119
119
|
# because we are not fetching a specific attribute yet, there is NO communication with the
|
120
120
|
# server. That only happens during find.
|
121
|
+
|
122
|
+
return DummyPolymorph.new(vector) unless model
|
123
|
+
|
121
124
|
model = model.base_class
|
122
125
|
|
123
126
|
# do we already have a record with this vector? If so return it, otherwise make a new one.
|
@@ -147,7 +150,7 @@ module ReactiveRecord
|
|
147
150
|
@attributes = {}
|
148
151
|
@changed_attributes = []
|
149
152
|
@virgin = true
|
150
|
-
records[model] << self
|
153
|
+
records[model.base_class] << self
|
151
154
|
Base.set_object_id_lookup(self)
|
152
155
|
end
|
153
156
|
|
@@ -204,7 +207,7 @@ module ReactiveRecord
|
|
204
207
|
end
|
205
208
|
|
206
209
|
def errors
|
207
|
-
@errors ||= ActiveModel::Errors.new(
|
210
|
+
@errors ||= ActiveModel::Errors.new(ar_instance)
|
208
211
|
end
|
209
212
|
|
210
213
|
# called when we have a newly created record, to initialize
|
@@ -250,7 +253,7 @@ module ReactiveRecord
|
|
250
253
|
return if @create_sync
|
251
254
|
@create_sync = true
|
252
255
|
end
|
253
|
-
model.unscoped
|
256
|
+
model.unscoped._internal_push ar_instance
|
254
257
|
@synced_with_unscoped = !@synced_with_unscoped
|
255
258
|
end
|
256
259
|
|
@@ -307,9 +310,11 @@ module ReactiveRecord
|
|
307
310
|
@saving = true
|
308
311
|
end
|
309
312
|
|
310
|
-
def errors!(hash)
|
313
|
+
def errors!(hash, saving)
|
314
|
+
@errors_at_last_sync = hash if saving
|
311
315
|
notify_waiting_for_save
|
312
316
|
errors.clear && return unless hash
|
317
|
+
errors.non_reactive_clear
|
313
318
|
hash.each do |attribute, messages|
|
314
319
|
messages.each do |message|
|
315
320
|
errors.add(attribute, message)
|
@@ -317,6 +322,11 @@ module ReactiveRecord
|
|
317
322
|
end
|
318
323
|
end
|
319
324
|
|
325
|
+
def revert_errors!
|
326
|
+
puts "#{inspect}.revert_errors! @errors_at_last_sync: #{@errors_at_last_sync}"
|
327
|
+
errors!(@errors_at_last_sync)
|
328
|
+
end
|
329
|
+
|
320
330
|
def saved!(save_only = nil) # sets saving to false AND notifies
|
321
331
|
notify_waiting_for_save
|
322
332
|
return self if save_only
|
@@ -418,6 +428,7 @@ module ReactiveRecord
|
|
418
428
|
|
419
429
|
def destroy_associations
|
420
430
|
@destroyed = false
|
431
|
+
@being_destroyed = true
|
421
432
|
model.reflect_on_all_associations.each do |association|
|
422
433
|
if association.collection?
|
423
434
|
@attributes[association.attribute].replace([]) if @attributes[association.attribute]
|
@@ -77,6 +77,8 @@ module ReactiveRecord
|
|
77
77
|
(@collection.length..index).each do |i|
|
78
78
|
new_dummy_record = ReactiveRecord::Base.new_from_vector(@target_klass, nil, *@vector, "*#{i}")
|
79
79
|
new_dummy_record.attributes[@association.inverse_of] = @owner if @association && !@association.through_association?
|
80
|
+
# HMT-TODO: the above needs to be looked into... if we are a hmt then don't we need to create a dummy on the joins collection as well?
|
81
|
+
# or maybe this just does not work for HMT?
|
80
82
|
@collection << new_dummy_record
|
81
83
|
end
|
82
84
|
end
|
@@ -212,7 +214,7 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
212
214
|
return [] unless attrs[@association.inverse_of] == @owner
|
213
215
|
if !@association.through_association
|
214
216
|
[record]
|
215
|
-
elsif (source = attrs[@association.source])
|
217
|
+
elsif (source = attrs[@association.source]) && source.is_a?(@target_klass)
|
216
218
|
[source]
|
217
219
|
else
|
218
220
|
[]
|
@@ -233,7 +235,8 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
233
235
|
end
|
234
236
|
|
235
237
|
def in_this_collection(related_records)
|
236
|
-
|
238
|
+
# HMT-TODO: I don't think we can get a set of related records here with a through association unless they are part of the collection
|
239
|
+
return related_records if !@association || @association.through_association?
|
237
240
|
related_records.select do |r|
|
238
241
|
r.backing_record.attributes[@association.inverse_of] == @owner
|
239
242
|
end
|
@@ -406,7 +409,11 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
406
409
|
def set_belongs_to(child)
|
407
410
|
if @owner
|
408
411
|
# TODO this is major broken...current
|
409
|
-
|
412
|
+
if (through_association = @association.through_association)
|
413
|
+
# HMT-TODO: create a new record with owner and child
|
414
|
+
else
|
415
|
+
child.send("#{@association.inverse_of}=", @owner) if @association && !@association.through_association
|
416
|
+
end
|
410
417
|
elsif @parent
|
411
418
|
@parent.set_belongs_to(child)
|
412
419
|
end
|
@@ -421,19 +428,40 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
421
428
|
|
422
429
|
def update_child(item)
|
423
430
|
backing_record = item.backing_record
|
424
|
-
|
431
|
+
# HMT TODO: The following && !association.through_association was commented out, causing wrong class items to be added to
|
432
|
+
# associations
|
433
|
+
# Why was it commented out.
|
434
|
+
if backing_record && @owner && @association && item.attributes[@association.inverse_of] != @owner && !@association.through_association?
|
425
435
|
inverse_of = @association.inverse_of
|
426
|
-
|
436
|
+
current_association_value = item.attributes[inverse_of]
|
427
437
|
backing_record.virgin = false unless backing_record.data_loading?
|
438
|
+
# next line was commented out and following line was active.
|
428
439
|
backing_record.update_belongs_to(inverse_of, @owner)
|
429
|
-
|
430
|
-
|
431
|
-
|
440
|
+
#backing_record.set_belongs_to_via_has_many(@association, @owner)
|
441
|
+
# following is handled by update_belongs_to and is redundant
|
442
|
+
# unless current_association_value.nil? # might be a dummy value which responds to nil
|
443
|
+
# current_association = @association.inverse.inverse(current_association_value)
|
444
|
+
# current_association_attribute = current_association.attribute
|
445
|
+
# if current_association.collection? && current_association_value.attributes[current_association_attribute]
|
446
|
+
# current_association.attributes[current_association_attribute].delete(item)
|
447
|
+
# end
|
448
|
+
# end
|
432
449
|
@owner.backing_record.sync_has_many(@association.attribute)
|
433
450
|
end
|
434
451
|
end
|
435
452
|
|
436
453
|
def push(item)
|
454
|
+
if (through_association = @association&.through_association)
|
455
|
+
through_association.klass.create(@association.inverse_of => @owner, @association.source => item)
|
456
|
+
self
|
457
|
+
else
|
458
|
+
_internal_push(item)
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
alias << push
|
463
|
+
|
464
|
+
def _internal_push(item)
|
437
465
|
item.itself # force get of at least the id
|
438
466
|
if collection
|
439
467
|
self.force_push item
|
@@ -449,8 +477,6 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
449
477
|
self
|
450
478
|
end
|
451
479
|
|
452
|
-
alias << push
|
453
|
-
|
454
480
|
def sort!(*args, &block)
|
455
481
|
replace(sort(*args, &block))
|
456
482
|
end
|
@@ -514,19 +540,19 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
514
540
|
@dummy_collection.notify
|
515
541
|
array = new_array.is_a?(Collection) ? new_array.collection : new_array
|
516
542
|
@collection.each_with_index do |r, i|
|
517
|
-
r.id = new_array[i].id if array[i] and array[i].id and !r.
|
543
|
+
r.id = new_array[i].id if array[i] and array[i].id and !r.new_record? and r.backing_record.vector.last =~ /^\*[0-9]+$/
|
518
544
|
end
|
519
545
|
end
|
520
|
-
|
521
|
-
@collection.dup.each { |item| delete(item) } if @collection
|
546
|
+
# the following makes sure that the existing elements are properly removed from the collection
|
547
|
+
@collection.dup.each { |item| delete(item) } if @collection
|
522
548
|
@collection = []
|
523
549
|
if new_array.is_a? Collection
|
524
550
|
@dummy_collection = new_array.dummy_collection
|
525
551
|
@dummy_record = new_array.dummy_record
|
526
|
-
new_array.collection.each { |item|
|
552
|
+
new_array.collection.each { |item| _internal_push item } if new_array.collection
|
527
553
|
else
|
528
554
|
@dummy_collection = @dummy_record = nil
|
529
|
-
new_array.each { |item|
|
555
|
+
new_array.each { |item| _internal_push item }
|
530
556
|
end
|
531
557
|
notify_of_change new_array
|
532
558
|
end
|
@@ -534,9 +560,9 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
534
560
|
def delete(item)
|
535
561
|
unsaved_children.delete(item)
|
536
562
|
notify_of_change(
|
537
|
-
if @owner && @association
|
563
|
+
if @owner && @association
|
538
564
|
inverse_of = @association.inverse_of
|
539
|
-
if (backing_record = item.backing_record) && item.attributes[inverse_of] == @owner
|
565
|
+
if (backing_record = item.backing_record) && item.attributes[inverse_of] == @owner && !@association.through_association?
|
540
566
|
# the if prevents double update if delete is being called from << (see << above)
|
541
567
|
backing_record.update_belongs_to(inverse_of, nil)
|
542
568
|
end
|
@@ -562,20 +588,8 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
562
588
|
@dummy_collection.loading?
|
563
589
|
end
|
564
590
|
|
565
|
-
def loaded?
|
566
|
-
false && @collection && (!@dummy_collection || !@dummy_collection.loading?) && (!@owner || @owner.id || @vector.length > 1)
|
567
|
-
end
|
568
|
-
|
569
|
-
def empty?
|
570
|
-
# should be handled by method missing below, but opal-rspec does not deal well
|
571
|
-
# with method missing, so to test...
|
572
|
-
all.empty?
|
573
|
-
end
|
574
|
-
|
575
591
|
def find_by(attrs)
|
576
592
|
attrs = @target_klass.__hyperstack_preprocess_attrs(attrs)
|
577
|
-
# r = @collection&.detect { |lr| lr.new_record? && !attrs.detect { |k, v| lr.attributes[k] != v } }
|
578
|
-
# return r if r
|
579
593
|
(r = __hyperstack_internal_scoped_find_by(attrs)) || return
|
580
594
|
r.backing_record.sync_attributes(attrs).set_ar_instance!
|
581
595
|
end
|
@@ -596,6 +610,16 @@ To determine this sync_scopes first asks if the record being changed is in the s
|
|
596
610
|
found
|
597
611
|
end
|
598
612
|
|
613
|
+
# to avoid fetching the entire collection array we check empty and any against the count
|
614
|
+
|
615
|
+
def empty?
|
616
|
+
count.zero?
|
617
|
+
end
|
618
|
+
|
619
|
+
def any?
|
620
|
+
!count.zero?
|
621
|
+
end
|
622
|
+
|
599
623
|
def method_missing(method, *args, &block)
|
600
624
|
if args.count == 1 && method.start_with?('find_by_')
|
601
625
|
find_by(method.sub(/^find_by_/, '') => args[0])
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ReactiveRecord
|
2
|
+
class DummyPolymorph
|
3
|
+
def initialize(vector)
|
4
|
+
@vector = vector
|
5
|
+
puts "VECTOR: #{@vector.inspect}"
|
6
|
+
Base.load_from_db(nil, *vector, 'id')
|
7
|
+
Base.load_from_db(nil, *vector, 'model_name')
|
8
|
+
end
|
9
|
+
|
10
|
+
def nil?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(*)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.reflect_on_all_associations(*)
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -4,9 +4,13 @@ module ReactiveRecord
|
|
4
4
|
module Getters
|
5
5
|
def get_belongs_to(assoc, reload = nil)
|
6
6
|
getter_common(assoc.attribute, reload) do |has_key, attr|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
next if new?
|
8
|
+
if id.present?
|
9
|
+
value = fetch_by_id(attr, @model.primary_key)
|
10
|
+
klass = fetch_by_id(attr, 'model_name')
|
11
|
+
klass &&= Object.const_get(klass)
|
12
|
+
end
|
13
|
+
value = find_association(assoc, value, klass)
|
10
14
|
sync_ignore_dummy attr, value, has_key
|
11
15
|
end&.cast_to_current_sti_type
|
12
16
|
end
|
@@ -104,18 +108,26 @@ module ReactiveRecord
|
|
104
108
|
else
|
105
109
|
virtual_fetch_on_server_warning(attribute) if on_opal_server? && changed?
|
106
110
|
yield false, attribute
|
107
|
-
end.tap {
|
111
|
+
end.tap { Hyperstack::Internal::State::Variable.get(self, attribute) unless data_loading? }
|
108
112
|
end
|
109
113
|
|
110
|
-
def find_association(association, id)
|
111
|
-
inverse_of = association.inverse_of
|
114
|
+
def find_association(association, id, klass)
|
112
115
|
instance = if id
|
113
|
-
find(
|
116
|
+
find(klass, klass.primary_key => id)
|
117
|
+
elsif association.polymorphic?
|
118
|
+
new_from_vector(nil, nil, *vector, association.attribute)
|
114
119
|
else
|
115
120
|
new_from_vector(association.klass, nil, *vector, association.attribute)
|
116
121
|
end
|
122
|
+
return instance if instance.is_a? DummyPolymorph
|
123
|
+
inverse_of = association.inverse_of(instance)
|
117
124
|
instance_backing_record_attributes = instance.attributes
|
118
125
|
inverse_association = association.klass.reflect_on_association(inverse_of)
|
126
|
+
# HMT-TODO: don't we need to do something with the through association case.
|
127
|
+
# perhaps we never hit this point...
|
128
|
+
if association.through_association?
|
129
|
+
IsomorphicHelpers.log "*********** called #{ar_instance}.find_association(#{association.attribute}) which is has many through!!!!!!!", :error
|
130
|
+
end
|
119
131
|
if inverse_association.collection?
|
120
132
|
instance_backing_record_attributes[inverse_of] = if id and id != ""
|
121
133
|
Collection.new(@model, instance, inverse_association, association.klass, ["find", id], inverse_of)
|
@@ -135,7 +135,6 @@ module ReactiveRecord
|
|
135
135
|
model.columns_hash[method_name] || model.server_methods[method_name]
|
136
136
|
end
|
137
137
|
|
138
|
-
|
139
138
|
class << self
|
140
139
|
|
141
140
|
attr_reader :pending_fetches
|
@@ -234,7 +233,7 @@ module ReactiveRecord
|
|
234
233
|
if association.collection?
|
235
234
|
# following line changed from .all to .collection on 10/28
|
236
235
|
[*value.collection, *value.unsaved_children].each do |assoc|
|
237
|
-
add_new_association.call(record, attribute, assoc.backing_record) if assoc.changed?(association.inverse_of) or assoc.
|
236
|
+
add_new_association.call(record, attribute, assoc.backing_record) if assoc.changed?(association.inverse_of(assoc)) or assoc.new_record?
|
238
237
|
end
|
239
238
|
elsif record.new? || record.changed?(attribute) || (record == record_being_saved && force)
|
240
239
|
if value.nil?
|
@@ -243,7 +242,7 @@ module ReactiveRecord
|
|
243
242
|
add_new_association.call record, attribute, value.backing_record
|
244
243
|
end
|
245
244
|
end
|
246
|
-
elsif aggregation = record.model.reflect_on_aggregation(attribute)
|
245
|
+
elsif (aggregation = record.model.reflect_on_aggregation(attribute)) && (aggregation.klass < ActiveRecord::Base)
|
247
246
|
add_new_association.call record, attribute, value.backing_record unless value.nil?
|
248
247
|
elsif aggregation
|
249
248
|
new_value = aggregation.serialize(value)
|
@@ -264,8 +263,17 @@ module ReactiveRecord
|
|
264
263
|
HyperMesh.load do
|
265
264
|
ReactiveRecord.loads_pending! unless self.class.pending_fetches.empty?
|
266
265
|
end.then { send_save_to_server(save, validate, force, &block) }
|
267
|
-
#save_to_server(validate, force, &block)
|
268
266
|
else
|
267
|
+
if validate
|
268
|
+
# Handles the case where a model is valid, then some attribute is
|
269
|
+
# updated, and model.validate is called updating the error data.
|
270
|
+
# Now lets say the attribute changes back to the last synced value. In
|
271
|
+
# this case we need to revert the error records.
|
272
|
+
models, _, backing_records = self.class.gather_records([self], true, self)
|
273
|
+
models.each do |item|
|
274
|
+
backing_records[item[:id]].revert_errors!
|
275
|
+
end
|
276
|
+
end
|
269
277
|
promise = Promise.new
|
270
278
|
yield true, nil, [] if block
|
271
279
|
promise.resolve({success: true})
|
@@ -302,14 +310,13 @@ module ReactiveRecord
|
|
302
310
|
|
303
311
|
response[:saved_models].each do | item |
|
304
312
|
backing_records[item[0]].sync_unscoped_collection! if save
|
305
|
-
backing_records[item[0]].errors! item[3]
|
313
|
+
backing_records[item[0]].errors! item[3], save
|
306
314
|
end
|
307
315
|
|
308
316
|
yield response[:success], response[:message], response[:models] if block
|
309
317
|
promise.resolve response # TODO this could be problematic... there was no .json here, so .... what's to do?
|
310
318
|
|
311
319
|
rescue Exception => e
|
312
|
-
# debugger
|
313
320
|
log("Exception raised while saving - #{e}", :error)
|
314
321
|
ensure
|
315
322
|
backing_records.each { |_id, record| record.saved! rescue nil } if save
|
@@ -454,6 +461,11 @@ module ReactiveRecord
|
|
454
461
|
elsif parent.class.reflect_on_association(association[:attribute].to_sym).collection?
|
455
462
|
#puts ">>>>>>>>>> #{parent.class.name}.send('#{association[:attribute]}') << #{reactive_records[association[:child_id]]})"
|
456
463
|
dont_save_list.delete(parent)
|
464
|
+
|
465
|
+
|
466
|
+
# if reactive_records[association[:child_id]]&.new_record?
|
467
|
+
# dont_save_list << reactive_records[association[:child_id]]
|
468
|
+
# end
|
457
469
|
#if false and parent.new?
|
458
470
|
#parent.send("#{association[:attribute]}") << reactive_records[association[:child_id]]
|
459
471
|
# puts "updated"
|
@@ -464,10 +476,13 @@ module ReactiveRecord
|
|
464
476
|
#puts ">>>>ASSOCIATION>>>> #{parent.class.name}.send('#{association[:attribute]}=', #{reactive_records[association[:child_id]]})"
|
465
477
|
parent.send("#{association[:attribute]}=", reactive_records[association[:child_id]])
|
466
478
|
dont_save_list.delete(parent)
|
467
|
-
|
479
|
+
|
480
|
+
# if parent.class.reflect_on_association(association[:attribute].to_sym).macro == :has_one &&
|
481
|
+
# reactive_records[association[:child_id]]&.new_record?
|
482
|
+
# dont_save_list << reactive_records[association[:child_id]]
|
483
|
+
# end
|
468
484
|
end
|
469
485
|
end if associations
|
470
|
-
|
471
486
|
# get rid of any records that don't require further processing, as a side effect
|
472
487
|
# we also save any records that need to be saved (these may be rolled back later.)
|
473
488
|
|
@@ -476,7 +491,9 @@ module ReactiveRecord
|
|
476
491
|
next true if record.frozen? # skip (but process later) frozen records
|
477
492
|
next true if dont_save_list.include?(record) # skip if the record is on the don't save list
|
478
493
|
next true if record.changed.include?(record.class.primary_key) # happens on an aggregate
|
479
|
-
next
|
494
|
+
#next true if record.persisted? # record may be have been saved as result of has_one assignment
|
495
|
+
# next false if record.id && !record.changed? # throw out any existing records with no changes
|
496
|
+
next record.persisted? if record.id && !record.changed?
|
480
497
|
# if we get to here save the record and return true to keep it
|
481
498
|
op = new_models.include?(record) ? :create_permitted? : :update_permitted?
|
482
499
|
record.check_permission_with_acting_user(acting_user, op).save(validate: false) || true
|
@@ -492,14 +509,15 @@ module ReactiveRecord
|
|
492
509
|
# the all the error messages during a save so we can dump them to the server log.
|
493
510
|
|
494
511
|
all_messages = []
|
512
|
+
attributes = nil
|
495
513
|
|
496
514
|
saved_models = reactive_records.collect do |reactive_record_id, model|
|
497
515
|
messages = model.errors.messages if validate && !model.valid?
|
498
516
|
all_messages << [model, messages] if save && messages
|
499
517
|
attributes = model.__hyperstack_secure_attributes(acting_user)
|
518
|
+
attributes[model.class.primary_key] = model[model.class.primary_key]
|
500
519
|
[reactive_record_id, model.class.name, attributes, messages]
|
501
520
|
end
|
502
|
-
|
503
521
|
# if we are not saving (i.e. just validating) then we rollback the transaction
|
504
522
|
|
505
523
|
raise ActiveRecord::Rollback, 'This Rollback is intentional!' unless save
|
@@ -514,7 +532,6 @@ module ReactiveRecord
|
|
514
532
|
end
|
515
533
|
raise 'HyperModel saving records failed!'
|
516
534
|
end
|
517
|
-
|
518
535
|
end
|
519
536
|
|
520
537
|
{ success: true, saved_models: saved_models }
|