iknow_view_models 2.10.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +119 -0
  3. data/.travis.yml +31 -0
  4. data/Appraisals +6 -16
  5. data/gemfiles/{rails_7_0.gemfile → rails_6_0_beta.gemfile} +2 -2
  6. data/iknow_view_models.gemspec +3 -5
  7. data/lib/iknow_view_models/version.rb +1 -1
  8. data/lib/view_model/active_record/association_data.rb +206 -92
  9. data/lib/view_model/active_record/association_manipulation.rb +22 -12
  10. data/lib/view_model/active_record/cache/cacheable_view.rb +3 -13
  11. data/lib/view_model/active_record/cache.rb +2 -2
  12. data/lib/view_model/active_record/cloner.rb +11 -11
  13. data/lib/view_model/active_record/controller.rb +0 -2
  14. data/lib/view_model/active_record/update_context.rb +21 -3
  15. data/lib/view_model/active_record/update_data.rb +43 -45
  16. data/lib/view_model/active_record/update_operation.rb +265 -153
  17. data/lib/view_model/active_record/visitor.rb +9 -6
  18. data/lib/view_model/active_record.rb +94 -74
  19. data/lib/view_model/after_transaction_runner.rb +3 -18
  20. data/lib/view_model/callbacks.rb +2 -2
  21. data/lib/view_model/changes.rb +24 -16
  22. data/lib/view_model/config.rb +6 -2
  23. data/lib/view_model/deserialization_error.rb +31 -0
  24. data/lib/view_model/deserialize_context.rb +2 -6
  25. data/lib/view_model/error_view.rb +6 -5
  26. data/lib/view_model/record/attribute_data.rb +11 -6
  27. data/lib/view_model/record.rb +44 -24
  28. data/lib/view_model/serialize_context.rb +2 -63
  29. data/lib/view_model/test_helpers/arvm_builder.rb +2 -4
  30. data/lib/view_model/traversal_context.rb +2 -2
  31. data/lib/view_model.rb +21 -13
  32. data/shell.nix +1 -1
  33. data/test/helpers/arvm_test_models.rb +4 -12
  34. data/test/helpers/arvm_test_utilities.rb +6 -0
  35. data/test/helpers/controller_test_helpers.rb +6 -6
  36. data/test/helpers/viewmodel_spec_helpers.rb +63 -52
  37. data/test/unit/view_model/access_control_test.rb +88 -37
  38. data/test/unit/view_model/active_record/belongs_to_test.rb +110 -178
  39. data/test/unit/view_model/active_record/cache_test.rb +11 -5
  40. data/test/unit/view_model/active_record/cloner_test.rb +1 -1
  41. data/test/unit/view_model/active_record/controller_test.rb +12 -20
  42. data/test/unit/view_model/active_record/has_many_test.rb +540 -316
  43. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +12 -15
  44. data/test/unit/view_model/active_record/has_many_through_test.rb +15 -58
  45. data/test/unit/view_model/active_record/has_one_test.rb +288 -135
  46. data/test/unit/view_model/active_record/poly_test.rb +0 -1
  47. data/test/unit/view_model/active_record/shared_test.rb +21 -39
  48. data/test/unit/view_model/active_record/version_test.rb +3 -2
  49. data/test/unit/view_model/active_record_test.rb +5 -63
  50. data/test/unit/view_model/callbacks_test.rb +1 -0
  51. data/test/unit/view_model/record_test.rb +0 -32
  52. data/test/unit/view_model/traversal_context_test.rb +13 -12
  53. metadata +15 -25
  54. data/.github/workflows/gem-push.yml +0 -31
  55. data/.github/workflows/test.yml +0 -65
  56. data/gemfiles/rails_6_0.gemfile +0 -9
  57. data/gemfiles/rails_6_1.gemfile +0 -9
  58. data/test/unit/view_model/active_record/optional_attribute_view_test.rb +0 -58
@@ -190,6 +190,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
190
190
  end
191
191
 
192
192
  define_viewmodel do
193
+ root!
193
194
  attribute :val
194
195
  association :tree2
195
196
 
@@ -215,7 +216,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
215
216
 
216
217
  define_viewmodel do
217
218
  attribute :val
218
- association :tree1, shared: true, optional: false
219
+ association :tree1
219
220
  end
220
221
  end
221
222
  end
@@ -447,15 +448,16 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
447
448
  include ViewModelSpecHelpers::List
448
449
  extend Minitest::Spec::DSL
449
450
 
450
- def assert_changes_match(changes, new, deleted, children, attributes, associations)
451
+ def assert_changes_match(changes, n: false, d: false, nstc: false, refc: false, att: [], ass: [])
451
452
  assert_equal(
452
453
  changes,
453
454
  ViewModel::Changes.new(
454
- new: new,
455
- deleted: deleted,
456
- changed_children: children,
457
- changed_attributes: attributes,
458
- changed_associations: associations))
455
+ new: n,
456
+ deleted: d,
457
+ changed_nested_children: nstc,
458
+ changed_referenced_children: refc,
459
+ changed_attributes: att,
460
+ changed_associations: ass))
459
461
  end
460
462
 
461
463
  describe 'with parent and points-to child test models' do
@@ -479,7 +481,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
479
481
  vm = viewmodel_class.deserialize_from_view(view, deserialize_context: ctx)
480
482
 
481
483
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
482
- assert_changes_match(vm_changes, true, false, false, ['name'], [])
484
+ assert_changes_match(vm_changes, n: true, att: ['name'])
483
485
  end
484
486
 
485
487
  it 'records a destroyed model' do
@@ -489,7 +491,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
489
491
  vm.destroy!(deserialize_context: ctx)
490
492
 
491
493
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
492
- assert_changes_match(vm_changes, false, true, false, [], [])
494
+ assert_changes_match(vm_changes, d: true)
493
495
  end
494
496
 
495
497
  it 'records a change to an attribute' do
@@ -498,7 +500,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
498
500
  end
499
501
 
500
502
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
501
- assert_changes_match(vm_changes, false, false, false, ['name'], [])
503
+ assert_changes_match(vm_changes, att: ['name'])
502
504
  end
503
505
 
504
506
  it 'records a new child' do
@@ -507,10 +509,10 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
507
509
  end
508
510
 
509
511
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
510
- assert_changes_match(vm_changes, false, false, true, [], ['child'])
512
+ assert_changes_match(vm_changes, nstc: true, ass: ['child'])
511
513
 
512
514
  c_changes = ctx.valid_edit_changes(vm.child.to_reference)
513
- assert_changes_match(c_changes, true, false, false, ['name'], [])
515
+ assert_changes_match(c_changes, n: true, att: ['name'])
514
516
  end
515
517
 
516
518
  it 'records a replaced child' do
@@ -522,14 +524,14 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
522
524
  end
523
525
 
524
526
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
525
- assert_changes_match(vm_changes, false, false, true, [], ['child'])
527
+ assert_changes_match(vm_changes, nstc: true, ass: ['child'])
526
528
 
527
529
  c_changes = ctx.valid_edit_changes(vm.child.to_reference)
528
- assert_changes_match(c_changes, true, false, false, ['name'], [])
530
+ assert_changes_match(c_changes, n: true, att: ['name'])
529
531
 
530
532
  oc_changes = ctx.valid_edit_changes(
531
533
  ViewModel::Reference.new(child_viewmodel_class, old_child.id))
532
- assert_changes_match(oc_changes, false, true, false, [], [])
534
+ assert_changes_match(oc_changes, d: true)
533
535
  end
534
536
 
535
537
  it 'records an edited child' do
@@ -542,10 +544,10 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
542
544
  # The parent node itself wasn't changed, so must not have been
543
545
  # valid_edit checked
544
546
  refute(ctx.was_edited?(vm.to_reference))
545
- assert_changes_match(vm.previous_changes, false, false, true, [], [])
547
+ assert_changes_match(vm.previous_changes, nstc: true)
546
548
 
547
549
  c_changes = ctx.valid_edit_changes(vm.child.to_reference)
548
- assert_changes_match(c_changes, false, false, false, ['name'], [])
550
+ assert_changes_match(c_changes, att: ['name'])
549
551
  end
550
552
 
551
553
  it 'records a deleted child' do
@@ -557,11 +559,11 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
557
559
  end
558
560
 
559
561
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
560
- assert_changes_match(vm_changes, false, false, true, [], ['child'])
562
+ assert_changes_match(vm_changes, nstc: true, ass: ['child'])
561
563
 
562
564
  oc_changes = ctx.valid_edit_changes(
563
565
  ViewModel::Reference.new(child_viewmodel_class, old_child.id))
564
- assert_changes_match(oc_changes, false, true, false, [], [])
566
+ assert_changes_match(oc_changes, d: true)
565
567
  end
566
568
  end
567
569
 
@@ -585,7 +587,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
585
587
  end
586
588
 
587
589
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
588
- assert_changes_match(vm_changes, false, false, true, [], ['children'])
590
+ assert_changes_match(vm_changes, nstc: true, ass: ['children'])
589
591
 
590
592
  new_children, existing_children = vm.children.partition do |c|
591
593
  c.name < 'm'
@@ -593,7 +595,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
593
595
 
594
596
  new_children.each do |c|
595
597
  c_changes = ctx.valid_edit_changes(c.to_reference)
596
- assert_changes_match(c_changes, true, false, false, ['name'], [])
598
+ assert_changes_match(c_changes, n: true, att: ['name'])
597
599
  end
598
600
 
599
601
  existing_children.each do |c|
@@ -613,15 +615,15 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
613
615
  refute(vm.children.include?(replaced_child))
614
616
 
615
617
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
616
- assert_changes_match(vm_changes, false, false, true, [], ['children'])
618
+ assert_changes_match(vm_changes, nstc: true, ass: ['children'])
617
619
 
618
620
  new_child = vm.children.detect { |c| c.name == 'b' }
619
621
  c_changes = ctx.valid_edit_changes(new_child.to_reference)
620
- assert_changes_match(c_changes, true, false, false, ['name'], [])
622
+ assert_changes_match(c_changes, n:true, att: ['name'])
621
623
 
622
624
  oc_changes = ctx.valid_edit_changes(
623
625
  ViewModel::Reference.new(child_viewmodel_class, replaced_child.id))
624
- assert_changes_match(oc_changes, false, true, false, [], [])
626
+ assert_changes_match(oc_changes, d: true)
625
627
  end
626
628
 
627
629
  it 'records reordered children' do
@@ -630,7 +632,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
630
632
  end
631
633
 
632
634
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
633
- assert_changes_match(vm_changes, false, false, false, [], ['children'])
635
+ assert_changes_match(vm_changes, ass: ['children'])
634
636
 
635
637
  vm.children.each do |c|
636
638
  refute(ctx.was_edited?(c.to_reference))
@@ -639,23 +641,23 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
639
641
  end
640
642
 
641
643
  describe 'with parent and shared child test models' do
642
- include ViewModelSpecHelpers::ParentAndSharedChild
644
+ include ViewModelSpecHelpers::ParentAndSharedBelongsToChild
643
645
 
644
646
  def new_model
645
647
  model_class.new(name: 'a', child: child_model_class.new(name: 'z'))
646
648
  end
647
649
 
648
- it 'records an change to child without a tree change' do
650
+ it 'records a change to child without a tree change' do
649
651
  vm, ctx = alter_by_view!(viewmodel_class, create_model!) do |view, refs|
650
652
  view['child'] = { '_ref' => 'cref' }
651
653
  refs.clear['cref'] = { '_type' => child_view_name, 'name' => 'b' }
652
654
  end
653
655
 
654
656
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
655
- assert_changes_match(vm_changes, false, false, false, [], ['child'])
657
+ assert_changes_match(vm_changes, ass: ['child'])
656
658
 
657
659
  c_changes = ctx.valid_edit_changes(vm.child.to_reference)
658
- assert_changes_match(c_changes, true, false, false, ['name'], [])
660
+ assert_changes_match(c_changes, n: true, att: ['name'])
659
661
  end
660
662
 
661
663
  it 'records an edited child without a tree change' do
@@ -664,10 +666,10 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
664
666
  end
665
667
 
666
668
  refute(ctx.was_edited?(vm.to_reference))
667
- assert_changes_match(vm.previous_changes, false, false, false, [], [])
669
+ assert_changes_match(vm.previous_changes)
668
670
 
669
671
  c_changes = ctx.valid_edit_changes(vm.child.to_reference)
670
- assert_changes_match(c_changes, false, false, false, ['name'], [])
672
+ assert_changes_match(c_changes, att: ['name'])
671
673
  end
672
674
 
673
675
  it 'records a deleted child' do
@@ -680,12 +682,61 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
680
682
  end
681
683
 
682
684
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
683
- assert_changes_match(vm_changes, false, false, false, [], ['child'])
685
+ assert_changes_match(vm_changes, ass: ['child'])
684
686
 
685
687
  refute(ctx.was_edited?(old_child.to_reference))
686
688
  end
687
689
  end
688
690
 
691
+ describe 'with parent and owned referenced child test models' do
692
+ include ViewModelSpecHelpers::ParentAndReferencedHasOneChild
693
+
694
+ def new_model
695
+ model_class.new(name: 'a', child: child_model_class.new(name: 'z'))
696
+ end
697
+
698
+ it 'records a change to child with referenced tree change' do
699
+ vm, ctx = alter_by_view!(viewmodel_class, create_model!) do |view, refs|
700
+ view['child'] = { '_ref' => 'cref' }
701
+ refs.clear['cref'] = { '_type' => child_view_name, 'name' => 'b' }
702
+ end
703
+
704
+ vm_changes = ctx.valid_edit_changes(vm.to_reference)
705
+ assert_changes_match(vm_changes, refc: true, ass: ['child'])
706
+
707
+ c_changes = ctx.valid_edit_changes(vm.child.to_reference)
708
+ assert_changes_match(c_changes, n: true, att: ['name'])
709
+ end
710
+
711
+ it 'records an edited child with referenced tree change' do
712
+ vm, ctx = alter_by_view!(viewmodel_class, create_model!) do |_view, refs|
713
+ refs.values.first.merge!('name' => 'b')
714
+ end
715
+
716
+ refute(ctx.was_edited?(vm.to_reference))
717
+ assert_changes_match(vm.previous_changes, refc: true)
718
+
719
+ c_changes = ctx.valid_edit_changes(vm.child.to_reference)
720
+ assert_changes_match(c_changes, att: ['name'])
721
+ end
722
+
723
+ it 'records a deleted child' do
724
+ vm = create_viewmodel!
725
+ old_child = vm.child
726
+
727
+ vm, ctx = alter_by_view!(viewmodel_class, vm.model) do |view, refs|
728
+ view['child'] = nil
729
+ refs.clear
730
+ end
731
+
732
+ vm_changes = ctx.valid_edit_changes(vm.to_reference)
733
+ assert_changes_match(vm_changes, refc: true, ass: ['child'])
734
+
735
+ c_changes = ctx.valid_edit_changes(old_child.to_reference)
736
+ assert_changes_match(c_changes, d: true)
737
+ end
738
+ end
739
+
689
740
  describe 'with has_many_through children test models' do
690
741
  include ViewModelSpecHelpers::ParentAndHasManyThroughChildren
691
742
 
@@ -706,7 +757,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
706
757
  end
707
758
 
708
759
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
709
- assert_changes_match(vm_changes, false, false, false, [], ['children'])
760
+ assert_changes_match(vm_changes, ass: ['children'])
710
761
 
711
762
  new_children, existing_children = vm.children.partition do |c|
712
763
  c.name < 'm'
@@ -714,7 +765,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
714
765
 
715
766
  new_children.each do |c|
716
767
  c_changes = ctx.valid_edit_changes(c.to_reference)
717
- assert_changes_match(c_changes, true, false, false, ['name'], [])
768
+ assert_changes_match(c_changes, n: true, att: ['name'])
718
769
  end
719
770
 
720
771
  existing_children.each do |c|
@@ -734,7 +785,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
734
785
  end
735
786
 
736
787
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
737
- assert_changes_match(vm_changes, false, false, false, [], ['children'])
788
+ assert_changes_match(vm_changes, ass: ['children'])
738
789
 
739
790
  new_children, existing_children = vm.children.partition do |c|
740
791
  c.name < 'm'
@@ -742,7 +793,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
742
793
 
743
794
  new_children.each do |c|
744
795
  c_changes = ctx.valid_edit_changes(c.to_reference)
745
- assert_changes_match(c_changes, true, false, false, ['name'], [])
796
+ assert_changes_match(c_changes, n: true, att: ['name'])
746
797
  end
747
798
 
748
799
  existing_children.each do |c|
@@ -758,7 +809,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
758
809
  end
759
810
 
760
811
  vm_changes = ctx.valid_edit_changes(vm.to_reference)
761
- assert_changes_match(vm_changes, false, false, false, [], ['children'])
812
+ assert_changes_match(vm_changes, ass: ['children'])
762
813
 
763
814
  vm.children.each do |c|
764
815
  refute(ctx.was_edited?(c.to_reference))