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.
- checksums.yaml +4 -4
- data/iknow_view_models.gemspec +1 -1
- data/lib/iknow_view_models/version.rb +1 -1
- data/lib/view_model/active_record/association_data.rb +206 -92
- data/lib/view_model/active_record/association_manipulation.rb +22 -12
- data/lib/view_model/active_record/cache/cacheable_view.rb +3 -13
- data/lib/view_model/active_record/cache.rb +2 -2
- data/lib/view_model/active_record/cloner.rb +11 -11
- data/lib/view_model/active_record/controller.rb +0 -2
- data/lib/view_model/active_record/update_context.rb +21 -3
- data/lib/view_model/active_record/update_data.rb +43 -45
- data/lib/view_model/active_record/update_operation.rb +265 -153
- data/lib/view_model/active_record/visitor.rb +9 -6
- data/lib/view_model/active_record.rb +94 -74
- data/lib/view_model/after_transaction_runner.rb +3 -18
- data/lib/view_model/changes.rb +24 -16
- data/lib/view_model/config.rb +6 -2
- data/lib/view_model/deserialization_error.rb +31 -0
- data/lib/view_model/deserialize_context.rb +2 -6
- data/lib/view_model/error_view.rb +6 -5
- data/lib/view_model/record/attribute_data.rb +11 -6
- data/lib/view_model/record.rb +44 -24
- data/lib/view_model/serialize_context.rb +2 -63
- data/lib/view_model.rb +17 -8
- data/shell.nix +1 -1
- data/test/helpers/arvm_test_utilities.rb +6 -0
- data/test/helpers/controller_test_helpers.rb +5 -3
- data/test/helpers/viewmodel_spec_helpers.rb +63 -52
- data/test/unit/view_model/access_control_test.rb +88 -37
- data/test/unit/view_model/active_record/belongs_to_test.rb +110 -178
- data/test/unit/view_model/active_record/cache_test.rb +3 -2
- data/test/unit/view_model/active_record/cloner_test.rb +1 -1
- data/test/unit/view_model/active_record/controller_test.rb +12 -20
- data/test/unit/view_model/active_record/has_many_test.rb +540 -316
- data/test/unit/view_model/active_record/has_many_through_poly_test.rb +12 -15
- data/test/unit/view_model/active_record/has_many_through_test.rb +15 -58
- data/test/unit/view_model/active_record/has_one_test.rb +288 -135
- data/test/unit/view_model/active_record/poly_test.rb +0 -1
- data/test/unit/view_model/active_record/shared_test.rb +21 -39
- data/test/unit/view_model/active_record/version_test.rb +3 -2
- data/test/unit/view_model/active_record_test.rb +5 -63
- data/test/unit/view_model/callbacks_test.rb +1 -0
- data/test/unit/view_model/record_test.rb +0 -32
- data/test/unit/view_model/traversal_context_test.rb +13 -12
- metadata +5 -8
- 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
|
-
#
|
50
|
-
#
|
51
|
-
#
|
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
|
55
|
-
#
|
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
|
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(
|
85
|
-
raise
|
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
|
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
|
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
|
-
|
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.
|
586
|
+
when association_data.referenced?
|
575
587
|
[]
|
576
|
-
when association_data.collection? #
|
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.
|
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.
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
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
|
-
|
705
|
-
|
706
|
-
|
706
|
+
unless valid_reference_keys.include?(ref)
|
707
|
+
raise ViewModel::DeserializationError::InvalidSharedReference.new(ref, blame_reference)
|
708
|
+
end
|
707
709
|
|
708
|
-
|
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] =
|