iknow_view_models 2.9.0 → 3.0.0

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/iknow_view_models.gemspec +1 -1
  3. data/lib/iknow_view_models/version.rb +1 -1
  4. data/lib/view_model/active_record/association_data.rb +206 -92
  5. data/lib/view_model/active_record/association_manipulation.rb +22 -12
  6. data/lib/view_model/active_record/cache/cacheable_view.rb +3 -13
  7. data/lib/view_model/active_record/cache.rb +2 -2
  8. data/lib/view_model/active_record/cloner.rb +11 -11
  9. data/lib/view_model/active_record/controller.rb +0 -2
  10. data/lib/view_model/active_record/update_context.rb +21 -3
  11. data/lib/view_model/active_record/update_data.rb +43 -45
  12. data/lib/view_model/active_record/update_operation.rb +265 -153
  13. data/lib/view_model/active_record/visitor.rb +9 -6
  14. data/lib/view_model/active_record.rb +94 -74
  15. data/lib/view_model/after_transaction_runner.rb +3 -18
  16. data/lib/view_model/changes.rb +24 -16
  17. data/lib/view_model/config.rb +6 -2
  18. data/lib/view_model/deserialization_error.rb +31 -0
  19. data/lib/view_model/deserialize_context.rb +2 -6
  20. data/lib/view_model/error_view.rb +6 -5
  21. data/lib/view_model/record/attribute_data.rb +11 -6
  22. data/lib/view_model/record.rb +44 -24
  23. data/lib/view_model/serialize_context.rb +2 -63
  24. data/lib/view_model.rb +17 -8
  25. data/shell.nix +1 -1
  26. data/test/helpers/arvm_test_utilities.rb +6 -0
  27. data/test/helpers/controller_test_helpers.rb +5 -3
  28. data/test/helpers/viewmodel_spec_helpers.rb +63 -52
  29. data/test/unit/view_model/access_control_test.rb +88 -37
  30. data/test/unit/view_model/active_record/belongs_to_test.rb +110 -178
  31. data/test/unit/view_model/active_record/cache_test.rb +3 -2
  32. data/test/unit/view_model/active_record/cloner_test.rb +1 -1
  33. data/test/unit/view_model/active_record/controller_test.rb +12 -20
  34. data/test/unit/view_model/active_record/has_many_test.rb +540 -316
  35. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +12 -15
  36. data/test/unit/view_model/active_record/has_many_through_test.rb +15 -58
  37. data/test/unit/view_model/active_record/has_one_test.rb +288 -135
  38. data/test/unit/view_model/active_record/poly_test.rb +0 -1
  39. data/test/unit/view_model/active_record/shared_test.rb +21 -39
  40. data/test/unit/view_model/active_record/version_test.rb +3 -2
  41. data/test/unit/view_model/active_record_test.rb +5 -63
  42. data/test/unit/view_model/callbacks_test.rb +1 -0
  43. data/test/unit/view_model/record_test.rb +0 -32
  44. data/test/unit/view_model/traversal_context_test.rb +13 -12
  45. metadata +5 -8
  46. data/test/unit/view_model/active_record/optional_attribute_view_test.rb +0 -58
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'renum'
2
4
  require 'view_model/schemas'
3
5
 
@@ -45,14 +47,13 @@ class ViewModel::ActiveRecord
45
47
  end
46
48
  end
47
49
 
48
- # Parser for collection updates. Collection updates have a regular
49
- # structure, but vary based on the contents. Parsing a {direct,
50
- # owned} collection recurses deeply and creates a tree of
51
- # UpdateDatas, while parsing a {through, shared} collection collects
52
- # reference strings.
50
+ # Parser for collection updates. Collection updates have a regular structure,
51
+ # but vary based on the contents. Parsing a nested collection recurses deeply
52
+ # and creates a tree of UpdateDatas, while parsing a referenced collection
53
+ # collects reference strings.
53
54
  class AbstractCollectionUpdate
54
- # Wraps a complete collection of new data: either UpdateDatas for owned
55
- # collections or reference strings for shared.
55
+ # Wraps a complete collection of new data: either UpdateDatas for non-root
56
+ # associations or reference strings for root.
56
57
  class Replace
57
58
  attr_reader :contents
58
59
  def initialize(contents)
@@ -61,7 +62,8 @@ class ViewModel::ActiveRecord
61
62
  end
62
63
 
63
64
  # Wraps an ordered list of FunctionalUpdates, each of whose `contents` are
64
- # either UpdateData for owned collections or references for shared.
65
+ # either UpdateData for nested associations or references for referenced
66
+ # associations.
65
67
  class Functional
66
68
  attr_reader :actions
67
69
  def initialize(actions)
@@ -81,8 +83,8 @@ class ViewModel::ActiveRecord
81
83
 
82
84
  # Resolve ViewModel::References used in the update's contents, whether by
83
85
  # reference or value.
84
- def used_vm_refs(update_context)
85
- raise "abstract"
86
+ def used_vm_refs(_update_context)
87
+ raise RuntimeError.new('abstract method')
86
88
  end
87
89
 
88
90
  def removed_vm_refs
@@ -153,7 +155,8 @@ class ViewModel::ActiveRecord
153
155
  # The shape of the actions are always the same
154
156
 
155
157
  # Parse an anchor for a functional_update, before/after
156
- # May only contain type and id fields, is never a reference even for shared collections.
158
+ # May only contain type and id fields, is never a reference even for
159
+ # referenced associations.
157
160
  def parse_anchor(child_hash) # final
158
161
  child_metadata = ViewModel.extract_reference_only_metadata(child_hash)
159
162
 
@@ -271,9 +274,13 @@ class ViewModel::ActiveRecord
271
274
 
272
275
  def used_vm_refs(update_context)
273
276
  update_datas
274
- .map { |upd| upd.viewmodel_reference if upd.id }
277
+ .map { |upd| resolve_vm_reference(upd, update_context) }
275
278
  .compact
276
279
  end
280
+
281
+ def resolve_vm_reference(update_data, _update_context)
282
+ update_data.viewmodel_reference if update_data.id
283
+ end
277
284
  end
278
285
 
279
286
  class Parser < AbstractCollectionUpdate::Parser
@@ -319,9 +326,13 @@ class ViewModel::ActiveRecord
319
326
 
320
327
  def used_vm_refs(update_context)
321
328
  references.map do |ref|
322
- update_context.resolve_reference(ref, nil).viewmodel_reference
329
+ resolve_vm_reference(ref, update_context)
323
330
  end
324
331
  end
332
+
333
+ def resolve_vm_reference(ref, update_context)
334
+ update_context.resolve_reference(ref, nil).viewmodel_reference
335
+ end
325
336
  end
326
337
 
327
338
  class Parser < AbstractCollectionUpdate::Parser
@@ -356,6 +367,7 @@ class ViewModel::ActiveRecord
356
367
  unless valid_reference_keys.include?(ref)
357
368
  raise ViewModel::DeserializationError::InvalidSharedReference.new(ref, blame_reference)
358
369
  end
370
+
359
371
  ref
360
372
  end
361
373
  end
@@ -421,7 +433,7 @@ class ViewModel::ActiveRecord
421
433
  fupdate_owned =
422
434
  fupdate_base.(ViewModel::Schemas::VIEWMODEL_UPDATE_SCHEMA)
423
435
 
424
- fupdate_shared =
436
+ fupdate_shared =
425
437
  fupdate_base.({ 'oneOf' => [ViewModel::Schemas::VIEWMODEL_REFERENCE_SCHEMA,
426
438
  viewmodel_reference_only] })
427
439
 
@@ -571,30 +583,15 @@ class ViewModel::ActiveRecord
571
583
  case
572
584
  when value.nil?
573
585
  []
574
- when association_data.shared?
586
+ when association_data.referenced?
575
587
  []
576
- when association_data.collection? # not shared, because of shared? check above
588
+ when association_data.collection? # nested, because of referenced? check above
577
589
  value.update_datas
578
590
  else
579
591
  [value]
580
592
  end
581
593
  end
582
594
 
583
- # Updates in terms of viewmodel associations
584
- def updated_associations
585
- deps = {}
586
-
587
- (associations.merge(referenced_associations)).each do |assoc_name, assoc_update|
588
- deps[assoc_name] =
589
- to_sequence(assoc_name, assoc_update)
590
- .each_with_object({}) do |update_data, updated_associations|
591
- updated_associations.deep_merge!(update_data.updated_associations)
592
- end
593
- end
594
-
595
- deps
596
- end
597
-
598
595
  def build_preload_specs(association_data, updates)
599
596
  if association_data.polymorphic?
600
597
  updates.map do |update_data|
@@ -682,6 +679,7 @@ class ViewModel::ActiveRecord
682
679
 
683
680
  when AssociationData
684
681
  association_data = member_data
682
+
685
683
  case
686
684
  when value.nil?
687
685
  if association_data.collection?
@@ -689,28 +687,28 @@ class ViewModel::ActiveRecord
689
687
  "Invalid collection update value 'nil' for association '#{name}'",
690
688
  blame_reference)
691
689
  end
692
- if association_data.shared?
690
+ if association_data.referenced?
693
691
  referenced_associations[name] = nil
694
692
  else
695
693
  associations[name] = nil
696
694
  end
697
695
 
698
- when association_data.through?
699
- referenced_associations[name] =
700
- ReferencedCollectionUpdate::Parser
701
- .new(association_data, blame_reference, valid_reference_keys)
702
- .parse(value)
696
+ when association_data.referenced?
697
+ if association_data.collection?
698
+ referenced_associations[name] =
699
+ ReferencedCollectionUpdate::Parser
700
+ .new(association_data, blame_reference, valid_reference_keys)
701
+ .parse(value)
702
+ else
703
+ # Extract and check reference
704
+ ref = ViewModel.extract_reference_metadata(value)
703
705
 
704
- when association_data.shared?
705
- # Extract and check reference
706
- ref = ViewModel.extract_reference_metadata(value)
706
+ unless valid_reference_keys.include?(ref)
707
+ raise ViewModel::DeserializationError::InvalidSharedReference.new(ref, blame_reference)
708
+ end
707
709
 
708
- unless valid_reference_keys.include?(ref)
709
- raise ViewModel::DeserializationError::InvalidSharedReference.new(ref, blame_reference)
710
+ referenced_associations[name] = ref
710
711
  end
711
-
712
- referenced_associations[name] = ref
713
-
714
712
  else
715
713
  if association_data.collection?
716
714
  associations[name] =