hyper-model 1.0.alpha1.2 → 1.0.alpha1.7

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.rspec +0 -1
  4. data/Gemfile +6 -5
  5. data/Rakefile +27 -3
  6. data/hyper-model.gemspec +11 -19
  7. data/lib/active_record_base.rb +105 -33
  8. data/lib/enumerable/pluck.rb +3 -2
  9. data/lib/hyper-model.rb +4 -1
  10. data/lib/hyper_model/version.rb +1 -1
  11. data/lib/hyper_react/input_tags.rb +2 -1
  12. data/lib/reactive_record/active_record/associations.rb +130 -34
  13. data/lib/reactive_record/active_record/base.rb +32 -0
  14. data/lib/reactive_record/active_record/class_methods.rb +124 -52
  15. data/lib/reactive_record/active_record/error.rb +2 -0
  16. data/lib/reactive_record/active_record/errors.rb +8 -4
  17. data/lib/reactive_record/active_record/instance_methods.rb +73 -5
  18. data/lib/reactive_record/active_record/public_columns_hash.rb +25 -26
  19. data/lib/reactive_record/active_record/reactive_record/backing_record_inspector.rb +22 -5
  20. data/lib/reactive_record/active_record/reactive_record/base.rb +50 -24
  21. data/lib/reactive_record/active_record/reactive_record/collection.rb +226 -68
  22. data/lib/reactive_record/active_record/reactive_record/dummy_polymorph.rb +22 -0
  23. data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +27 -15
  24. data/lib/reactive_record/active_record/reactive_record/getters.rb +33 -10
  25. data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +81 -51
  26. data/lib/reactive_record/active_record/reactive_record/lookup_tables.rb +5 -5
  27. data/lib/reactive_record/active_record/reactive_record/operations.rb +10 -3
  28. data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +3 -0
  29. data/lib/reactive_record/active_record/reactive_record/setters.rb +105 -68
  30. data/lib/reactive_record/active_record/reactive_record/while_loading.rb +249 -32
  31. data/lib/reactive_record/broadcast.rb +62 -25
  32. data/lib/reactive_record/interval.rb +3 -3
  33. data/lib/reactive_record/permissions.rb +14 -2
  34. data/lib/reactive_record/scope_description.rb +3 -2
  35. data/lib/reactive_record/server_data_cache.rb +99 -49
  36. data/polymorph-notes.md +143 -0
  37. data/spec_fails.txt +3 -0
  38. metadata +54 -153
  39. data/Gemfile.lock +0 -421
@@ -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
@@ -1,4 +1,4 @@
1
- # add mehods to Object to determine if this is a dummy object or not
1
+ # add methods to Object to determine if this is a dummy object or not
2
2
  class Object
3
3
  def loaded?
4
4
  !loading?
@@ -7,10 +7,6 @@ class Object
7
7
  def loading?
8
8
  false
9
9
  end
10
-
11
- def present?
12
- !!self
13
- end
14
10
  end
15
11
 
16
12
  module ReactiveRecord
@@ -36,6 +32,12 @@ module ReactiveRecord
36
32
  @column_hash[:default] || nil
37
33
  end
38
34
 
35
+ def build_default_value_for_json
36
+ ::JSON.parse(@column_hash[:default]) if @column_hash[:default]
37
+ end
38
+
39
+ alias build_default_value_for_jsonb build_default_value_for_json
40
+
39
41
  def build_default_value_for_datetime
40
42
  if @column_hash[:default]
41
43
  ::Time.parse(@column_hash[:default].gsub(' ','T')+'+00:00')
@@ -55,23 +57,26 @@ module ReactiveRecord
55
57
  end
56
58
  end
57
59
 
60
+ FALSY_VALUES = [false, nil, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
61
+
58
62
  def build_default_value_for_boolean
59
- @column_hash[:default] || false
63
+ !FALSY_VALUES.include?(@column_hash[:default])
60
64
  end
61
65
 
62
66
  def build_default_value_for_float
63
- @column_hash[:default] || Float(0.0)
67
+ @column_hash[:default]&.to_f || Float(0.0)
64
68
  end
65
69
 
66
70
  alias build_default_value_for_decimal build_default_value_for_float
67
71
 
68
72
  def build_default_value_for_integer
69
- @column_hash[:default] || Integer(0)
73
+ @column_hash[:default]&.to_i || Integer(0)
70
74
  end
71
75
 
72
76
  alias build_default_value_for_bigint build_default_value_for_integer
73
77
 
74
78
  def build_default_value_for_string
79
+ return @column_hash[:default] if @column_hash[:serialized?]
75
80
  @column_hash[:default] || ''
76
81
  end
77
82
 
@@ -91,10 +96,6 @@ module ReactiveRecord
91
96
  false
92
97
  end
93
98
 
94
- def present?
95
- false
96
- end
97
-
98
99
  def nil?
99
100
  true
100
101
  end
@@ -103,6 +104,11 @@ module ReactiveRecord
103
104
  true
104
105
  end
105
106
 
107
+ def class
108
+ notify
109
+ @object.class
110
+ end
111
+
106
112
  def method_missing(method, *args, &block)
107
113
  if method.start_with?("build_default_value_for_")
108
114
  nil
@@ -157,7 +163,13 @@ module ReactiveRecord
157
163
 
158
164
  alias inspect to_s
159
165
 
160
- `#{self}.$$proto.toString = Opal.Object.$$proto.toString`
166
+ %x{
167
+ if (Opal.Object.$$proto) {
168
+ #{self}.$$proto.toString = Opal.Object.$$proto.toString
169
+ } else {
170
+ #{self}.$$prototype.toString = Opal.Object.$$prototype.toString
171
+ }
172
+ }
161
173
 
162
174
  def to_f
163
175
  notify
@@ -215,10 +227,10 @@ module ReactiveRecord
215
227
  # to convert it to a string, for rendering
216
228
  # advantage over a try(:method) is, that it doesnt raise und thus is faster
217
229
  # which is important during render
218
- def respond_to?(method)
230
+ def respond_to?(method, all = false)
219
231
  return true if method == :acts_as_string?
220
232
  return true if %i[inspect to_date to_f to_i to_numeric to_number to_s to_time].include? method
221
- return @object.respond_to? if @object
233
+ return @object.respond_to?(method, all) if @object
222
234
  false
223
235
  end
224
236
 
@@ -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
- return if new?
8
- value = Base.fetch_from_db([@model, [:find, id], attr, @model.primary_key]) if id.present?
9
- value = find_association(assoc, value)
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
@@ -33,7 +37,8 @@ module ReactiveRecord
33
37
 
34
38
  def get_server_method(attr, reload = nil)
35
39
  non_relationship_getter_common(attr, reload) do |has_key|
36
- sync_ignore_dummy attr, Base.load_from_db(self, *(vector ? vector : [nil]), attr), has_key
40
+ # SPLAT BUG: was sync_ignore_dummy attr, Base.load_from_db(self, *(vector ? vector : [nil]), attr), has_key
41
+ sync_ignore_dummy attr, Base.load_from_db(self, *(vector || [nil]), *attr), has_key
37
42
  end
38
43
  end
39
44
 
@@ -75,10 +80,16 @@ module ReactiveRecord
75
80
  if new?
76
81
  yield has_key if block
77
82
  elsif on_opal_client?
78
- sync_ignore_dummy attr, Base.load_from_db(self, *(vector ? vector : [nil]), attr), has_key
83
+ # SPLAT BUG: was sync_ignore_dummy attr, Base.load_from_db(self, *(vector ? vector : [nil]), attr), has_key
84
+ sync_ignore_dummy attr, Base.load_from_db(self, *(vector || [nil]), *attr), has_key
79
85
  elsif id.present?
80
- sync_attribute attr, Base.fetch_from_db([@model, [:find, id], attr])
86
+ sync_attribute attr, fetch_by_id(attr)
81
87
  else
88
+ # Not sure how to test this branch, it may never execute this line?
89
+ # If we are on opal_server then we should always be getting an id before getting here
90
+ # but if we do vector might not be set up properly to fetch the attribute
91
+ puts "*** Syncing attribute in getters.rb without an id. This may cause problems. ***"
92
+ puts "*** Report this to hyperstack.org if you see this message: vector = #{[*vector, attr]}"
82
93
  sync_attribute attr, Base.fetch_from_db([*vector, attr])
83
94
  end
84
95
  end
@@ -99,18 +110,26 @@ module ReactiveRecord
99
110
  else
100
111
  virtual_fetch_on_server_warning(attribute) if on_opal_server? && changed?
101
112
  yield false, attribute
102
- end.tap { |value| Hyperstack::Internal::State::Variable.get(self, attribute) unless data_loading? }
113
+ end.tap { Hyperstack::Internal::State::Variable.get(self, attribute) unless data_loading? }
103
114
  end
104
115
 
105
- def find_association(association, id)
106
- inverse_of = association.inverse_of
116
+ def find_association(association, id, klass)
107
117
  instance = if id
108
- find(association.klass, association.klass.primary_key => id)
118
+ find(klass, klass.primary_key => id)
119
+ elsif association.polymorphic?
120
+ new_from_vector(nil, nil, *vector, association.attribute)
109
121
  else
110
122
  new_from_vector(association.klass, nil, *vector, association.attribute)
111
123
  end
124
+ return instance if instance.is_a? DummyPolymorph
125
+ inverse_of = association.inverse_of(instance)
112
126
  instance_backing_record_attributes = instance.attributes
113
127
  inverse_association = association.klass.reflect_on_association(inverse_of)
128
+ # HMT-TODO: don't we need to do something with the through association case.
129
+ # perhaps we never hit this point...
130
+ if association.through_association?
131
+ IsomorphicHelpers.log "*********** called #{ar_instance}.find_association(#{association.attribute}) which is has many through!!!!!!!", :error
132
+ end
114
133
  if inverse_association.collection?
115
134
  instance_backing_record_attributes[inverse_of] = if id and id != ""
116
135
  Collection.new(@model, instance, inverse_association, association.klass, ["find", id], inverse_of)
@@ -129,5 +148,9 @@ module ReactiveRecord
129
148
  self.aggregate_attribute = attr
130
149
  @ar_instance
131
150
  end
151
+
152
+ def fetch_by_id(*vector)
153
+ Base.fetch_from_db([@model, *find_by_vector(@model.primary_key => id), *vector])
154
+ end
132
155
  end
133
156
  end
@@ -1,5 +1,3 @@
1
- require 'json'
2
-
3
1
  module ReactiveRecord
4
2
 
5
3
  class Base
@@ -10,6 +8,7 @@ module ReactiveRecord
10
8
  if RUBY_ENGINE != 'opal'
11
9
  @server_data_cache = ReactiveRecord::ServerDataCache.new(context.controller.acting_user, {})
12
10
  else
11
+ Hyperstack::Internal::State::Variable.set(WhileLoading, :quiet, true)
13
12
  @public_columns_hash = get_public_columns_hash
14
13
  define_attribute_methods
15
14
  @outer_scopes = Set.new
@@ -46,6 +45,15 @@ module ReactiveRecord
46
45
  self.class.instance_variable_get(:@records)
47
46
  end
48
47
 
48
+ # constructs vector for find_by
49
+ def self.find_by_vector(attrs)
50
+ [:all, [:___hyperstack_internal_scoped_find_by, attrs], '*0']
51
+ end
52
+
53
+ def find_by_vector(attrs)
54
+ self.class.find_by_vector(attrs)
55
+ end
56
+
49
57
  # Prerendering db access (returns nil if on client):
50
58
  # at end of prerendering dumps all accessed records in the footer
51
59
 
@@ -57,7 +65,9 @@ module ReactiveRecord
57
65
 
58
66
  isomorphic_method(:find_in_db) do |f, klass, attrs|
59
67
  f.send_to_server klass.name, attrs if RUBY_ENGINE == 'opal'
60
- f.when_on_server { @server_data_cache[klass, ['find_by', attrs], 'id'] }
68
+ f.when_on_server do
69
+ @server_data_cache[klass, *find_by_vector(attrs), 'id']
70
+ end
61
71
  end
62
72
 
63
73
  class << self
@@ -123,7 +133,6 @@ module ReactiveRecord
123
133
  model.columns_hash[method_name] || model.server_methods[method_name]
124
134
  end
125
135
 
126
-
127
136
  class << self
128
137
 
129
138
  attr_reader :pending_fetches
@@ -222,7 +231,7 @@ module ReactiveRecord
222
231
  if association.collection?
223
232
  # following line changed from .all to .collection on 10/28
224
233
  [*value.collection, *value.unsaved_children].each do |assoc|
225
- add_new_association.call(record, attribute, assoc.backing_record) if assoc.changed?(association.inverse_of) or assoc.new?
234
+ add_new_association.call(record, attribute, assoc.backing_record) if assoc.changed?(association.inverse_of(assoc)) or assoc.new_record?
226
235
  end
227
236
  elsif record.new? || record.changed?(attribute) || (record == record_being_saved && force)
228
237
  if value.nil?
@@ -231,7 +240,7 @@ module ReactiveRecord
231
240
  add_new_association.call record, attribute, value.backing_record
232
241
  end
233
242
  end
234
- elsif aggregation = record.model.reflect_on_aggregation(attribute) and (aggregation.klass < ActiveRecord::Base)
243
+ elsif (aggregation = record.model.reflect_on_aggregation(attribute)) && (aggregation.klass < ActiveRecord::Base)
235
244
  add_new_association.call record, attribute, value.backing_record unless value.nil?
236
245
  elsif aggregation
237
246
  new_value = aggregation.serialize(value)
@@ -242,7 +251,7 @@ module ReactiveRecord
242
251
  end if record.new? || record.changed? || (record == record_being_saved && force)
243
252
  record_index += 1
244
253
  end
245
- [models, associations, backing_records]
254
+ [models.sort_by { |model| model[:id] }, associations, backing_records]
246
255
  end
247
256
 
248
257
  def save_or_validate(save, validate, force, &block)
@@ -252,8 +261,17 @@ module ReactiveRecord
252
261
  HyperMesh.load do
253
262
  ReactiveRecord.loads_pending! unless self.class.pending_fetches.empty?
254
263
  end.then { send_save_to_server(save, validate, force, &block) }
255
- #save_to_server(validate, force, &block)
256
264
  else
265
+ if validate
266
+ # Handles the case where a model is valid, then some attribute is
267
+ # updated, and model.validate is called updating the error data.
268
+ # Now lets say the attribute changes back to the last synced value. In
269
+ # this case we need to revert the error records.
270
+ models, _, backing_records = self.class.gather_records([self], true, self)
271
+ models.each do |item|
272
+ backing_records[item[:id]].revert_errors!
273
+ end
274
+ end
257
275
  promise = Promise.new
258
276
  yield true, nil, [] if block
259
277
  promise.resolve({success: true})
@@ -290,14 +308,13 @@ module ReactiveRecord
290
308
 
291
309
  response[:saved_models].each do | item |
292
310
  backing_records[item[0]].sync_unscoped_collection! if save
293
- backing_records[item[0]].errors! item[3]
311
+ backing_records[item[0]].errors! item[3], save
294
312
  end
295
313
 
296
314
  yield response[:success], response[:message], response[:models] if block
297
315
  promise.resolve response # TODO this could be problematic... there was no .json here, so .... what's to do?
298
316
 
299
317
  rescue Exception => e
300
- # debugger
301
318
  log("Exception raised while saving - #{e}", :error)
302
319
  ensure
303
320
  backing_records.each { |_id, record| record.saved! rescue nil } if save
@@ -316,25 +333,29 @@ module ReactiveRecord
316
333
 
317
334
  else
318
335
 
319
- def self.find_record(model, id, vector, save)
336
+ def self.find_record(model, id, acting_user, vector, save)
320
337
  if !save
321
338
  found = vector[1..-1].inject(vector[0]) do |object, method|
322
339
  if object.nil? # happens if you try to do an all on empty scope followed by more scopes
323
340
  object
324
- elsif method.is_a? Array
341
+ elsif method.is_a? Array #__secure_remote_access_to_
325
342
  if method[0] == 'new'
326
343
  object.new
327
344
  else
328
- object.send(*method)
345
+ object.send(:"__secure_remote_access_to_#{method[0]}", object, acting_user, *method[1..-1])
329
346
  end
330
- elsif method.is_a? String and method[0] == '*'
347
+ elsif method.is_a?(String) && method[0] == '*'
331
348
  object[method.gsub(/^\*/,'').to_i]
332
349
  else
333
- object.send(method)
350
+ object.send(:"__secure_remote_access_to_#{method}", object, acting_user)
334
351
  end
335
352
  end
336
353
  if id and (found.nil? or !(found.class <= model) or (found.id and found.id.to_s != id.to_s))
337
- raise "Inconsistent data sent to server - #{model.name}.find(#{id}) != [#{vector}]"
354
+ # TODO: the one case that this is okay is when we are doing a find(some_id) which
355
+ # does not exist. So the above check needs to deal with that if possible,
356
+ # otherwise we can just skip this check, as it was put in sometime back for
357
+ # debugging purposes, and is perhaps not necessary anymore
358
+ #raise "Inconsistent data sent to server - #{model.name}.find(#{id}) != [#{vector}]"
338
359
  end
339
360
  found
340
361
  elsif id
@@ -362,13 +383,13 @@ module ReactiveRecord
362
383
  id = attributes.delete(model.primary_key) if model.respond_to? :primary_key # if we are saving existing model primary key value will be present
363
384
  vector = model_to_save[:vector]
364
385
  vector = [vector[0].constantize] + vector[1..-1].collect do |method|
365
- if method.is_a?(Array) and method.first == "find_by_id"
386
+ if method.is_a?(Array) && method.first == "find_by_id"
366
387
  ["find", method.last]
367
388
  else
368
389
  method
369
390
  end
370
391
  end
371
- reactive_records[model_to_save[:id]] = vectors[vector] = record = find_record(model, id, vector, save) # ??? || validate ???
392
+ reactive_records[model_to_save[:id]] = vectors[vector] = record = find_record(model, id, acting_user, vector, save) # ??? || validate ???
372
393
  next unless record
373
394
  if attributes.empty?
374
395
  dont_save_list << record unless save
@@ -434,24 +455,29 @@ module ReactiveRecord
434
455
  parent.send("#{association[:attribute]}=", aggregate)
435
456
  #puts "updated is frozen? #{aggregate.frozen?}, parent attributes = #{parent.send(association[:attribute]).attributes}"
436
457
  elsif parent.class.reflect_on_association(association[:attribute].to_sym).nil?
437
- raise "Missing association :#{association[:attribute]} for #{parent.class.name}. Was association defined on opal side only?"
458
+ raise "Missing association :#{association[:attribute]} for #{parent.class.name}. Was association defined on opal side only?"
438
459
  elsif parent.class.reflect_on_association(association[:attribute].to_sym).collection?
439
460
  #puts ">>>>>>>>>> #{parent.class.name}.send('#{association[:attribute]}') << #{reactive_records[association[:child_id]]})"
440
461
  dont_save_list.delete(parent)
441
- #if false and parent.new?
442
- #parent.send("#{association[:attribute]}") << reactive_records[association[:child_id]]
443
- # puts "updated"
444
- #else
445
- #puts "skipped"
446
- #end
462
+
463
+ # if reactive_records[association[:child_id]]&.new_record?
464
+ # dont_save_list << reactive_records[association[:child_id]]
465
+ # end
466
+
467
+ if parent.new_record?
468
+ parent.send("#{association[:attribute]}") << reactive_records[association[:child_id]]
469
+ end
447
470
  else
448
471
  #puts ">>>>ASSOCIATION>>>> #{parent.class.name}.send('#{association[:attribute]}=', #{reactive_records[association[:child_id]]})"
449
472
  parent.send("#{association[:attribute]}=", reactive_records[association[:child_id]])
450
473
  dont_save_list.delete(parent)
451
- #puts "updated"
474
+
475
+ # if parent.class.reflect_on_association(association[:attribute].to_sym).macro == :has_one &&
476
+ # reactive_records[association[:child_id]]&.new_record?
477
+ # dont_save_list << reactive_records[association[:child_id]]
478
+ # end
452
479
  end
453
480
  end if associations
454
-
455
481
  # get rid of any records that don't require further processing, as a side effect
456
482
  # we also save any records that need to be saved (these may be rolled back later.)
457
483
 
@@ -460,10 +486,13 @@ module ReactiveRecord
460
486
  next true if record.frozen? # skip (but process later) frozen records
461
487
  next true if dont_save_list.include?(record) # skip if the record is on the don't save list
462
488
  next true if record.changed.include?(record.class.primary_key) # happens on an aggregate
463
- next false if record.id && !record.changed? # throw out any existing records with no changes
489
+ #next true if record.persisted? # record may be have been saved as result of has_one assignment
490
+ # next false if record.id && !record.changed? # throw out any existing records with no changes
491
+ next record.persisted? if record.id && !record.changed?
464
492
  # if we get to here save the record and return true to keep it
465
493
  op = new_models.include?(record) ? :create_permitted? : :update_permitted?
466
- record.check_permission_with_acting_user(acting_user, op).save(validate: false) || true
494
+
495
+ record.check_permission_with_acting_user(acting_user, op).save(validate: validate) || true
467
496
  end
468
497
 
469
498
  # if called from ServerDataCache then save and validate are both false, and we just return the
@@ -476,14 +505,15 @@ module ReactiveRecord
476
505
  # the all the error messages during a save so we can dump them to the server log.
477
506
 
478
507
  all_messages = []
508
+ attributes = nil
479
509
 
480
510
  saved_models = reactive_records.collect do |reactive_record_id, model|
481
511
  messages = model.errors.messages if validate && !model.valid?
482
512
  all_messages << [model, messages] if save && messages
483
513
  attributes = model.__hyperstack_secure_attributes(acting_user)
514
+ attributes[model.class.primary_key] = model[model.class.primary_key]
484
515
  [reactive_record_id, model.class.name, attributes, messages]
485
516
  end
486
-
487
517
  # if we are not saving (i.e. just validating) then we rollback the transaction
488
518
 
489
519
  raise ActiveRecord::Rollback, 'This Rollback is intentional!' unless save
@@ -498,7 +528,6 @@ module ReactiveRecord
498
528
  end
499
529
  raise 'HyperModel saving records failed!'
500
530
  end
501
-
502
531
  end
503
532
 
504
533
  { success: true, saved_models: saved_models }
@@ -507,7 +536,7 @@ module ReactiveRecord
507
536
  if save || validate
508
537
  {success: false, saved_models: saved_models, message: e}
509
538
  else
510
- {}
539
+ raise e # was returning {} TODO verify that just raising the error at least reports the error
511
540
  end
512
541
  end
513
542
 
@@ -518,25 +547,31 @@ module ReactiveRecord
518
547
  if RUBY_ENGINE == 'opal'
519
548
 
520
549
  def destroy(&block)
550
+ return if @destroyed || @being_destroyed
521
551
 
522
- return if @destroyed
523
-
524
- #destroy_associations
552
+ # destroy_associations
525
553
 
526
554
  promise = Promise.new
527
-
528
- if !data_loading? and (id or vector)
555
+ if !data_loading? && (id || vector)
529
556
  Operations::Destroy.run(model: ar_instance.model_name.to_s, id: id, vector: vector)
530
557
  .then do |response|
531
- Broadcast.to_self ar_instance
558
+ #[reactive_record_id, model.class.name, attributes, messages] model.errors.messages
559
+
560
+ if response[:success]
561
+ @destroyed = true
562
+ Broadcast.to_self ar_instance
563
+ else
564
+ errors! response[:messages]
565
+ end
532
566
  yield response[:success], response[:message] if block
533
567
  promise.resolve response
534
568
  end
535
569
  else
536
570
  destroy_associations
537
571
  # sync_unscoped_collection! # ? should we do this here was NOT being done before hypermesh integration
572
+ @destroyed = true
538
573
  yield true, nil if block
539
- promise.resolve({success: true})
574
+ promise.resolve(success: true)
540
575
  end
541
576
 
542
577
  # DO NOT CLEAR ATTRIBUTES. Records that are not found, are destroyed, and if they are searched for again, we want to make
@@ -546,8 +581,6 @@ module ReactiveRecord
546
581
  # sync!
547
582
  # and modify server_data_cache so that it does NOT call destroy
548
583
 
549
- @destroyed = true
550
-
551
584
  promise
552
585
  end
553
586
 
@@ -556,18 +589,15 @@ module ReactiveRecord
556
589
  def self.destroy_record(model, id, vector, acting_user)
557
590
  model = Object.const_get(model)
558
591
  record = if id
559
- model.find(id)
560
- else
561
- ServerDataCache.new(acting_user, {})[*vector]
562
- end
563
-
564
-
565
- record.check_permission_with_acting_user(acting_user, :destroy_permitted?).destroy
566
- {success: true, attributes: {}}
592
+ model.find(id)
593
+ else
594
+ ServerDataCache.new(acting_user, {})[*vector].value
595
+ end
567
596
 
597
+ success = record.check_permission_with_acting_user(acting_user, :destroy_permitted?).destroy
598
+ { success: success, attributes: {}, messages: record.errors.messages }
568
599
  rescue Exception => e
569
- #ReactiveRecord::Pry.rescued(e)
570
- {success: false, record: record, message: e}
600
+ { success: false, record: record, message: e }
571
601
  end
572
602
  end
573
603
  end