iknow_view_models 2.9.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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] =