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.
- 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
@@ -20,6 +20,7 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
20
20
|
end
|
21
21
|
|
22
22
|
define_viewmodel do
|
23
|
+
root!
|
23
24
|
attributes :name
|
24
25
|
end
|
25
26
|
end
|
@@ -37,6 +38,7 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
37
38
|
end
|
38
39
|
|
39
40
|
define_viewmodel do
|
41
|
+
root!
|
40
42
|
attributes :name
|
41
43
|
end
|
42
44
|
end
|
@@ -53,8 +55,9 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
53
55
|
end
|
54
56
|
|
55
57
|
define_viewmodel do
|
58
|
+
root!
|
56
59
|
attributes :name
|
57
|
-
association :tags,
|
60
|
+
association :tags, through: :parents_tags, through_order_attr: :position, viewmodels: [TagAView, TagBView]
|
58
61
|
end
|
59
62
|
end
|
60
63
|
end
|
@@ -86,10 +89,6 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
86
89
|
self.class.build_parent_tag_join_model(self)
|
87
90
|
end
|
88
91
|
|
89
|
-
private def context_with(*args)
|
90
|
-
ParentView.new_serialize_context(include: args)
|
91
|
-
end
|
92
|
-
|
93
92
|
def setup
|
94
93
|
super
|
95
94
|
|
@@ -108,14 +107,14 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
108
107
|
def test_roundtrip
|
109
108
|
# Objects are serialized to a view and deserialized, and should not be different when complete.
|
110
109
|
|
111
|
-
alter_by_view!(ParentView, @parent1
|
110
|
+
alter_by_view!(ParentView, @parent1) {}
|
112
111
|
assert_equal('p1', @parent1.name)
|
113
112
|
assert_equal([@tag_a1, @tag_a2, @tag_b1, @tag_b2],
|
114
113
|
@parent1.parents_tags.order(:position).map(&:tag))
|
115
114
|
end
|
116
115
|
|
117
116
|
def test_loading_batching
|
118
|
-
context =
|
117
|
+
context = ParentView.new_serialize_context
|
119
118
|
log_queries do
|
120
119
|
parent_views = ParentView.load(serialize_context: context)
|
121
120
|
serialize(parent_views, serialize_context: context)
|
@@ -126,7 +125,7 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
126
125
|
end
|
127
126
|
|
128
127
|
def test_eager_includes
|
129
|
-
includes = ParentView.eager_includes
|
128
|
+
includes = ParentView.eager_includes
|
130
129
|
assert_equal(DeepPreloader::Spec.new(
|
131
130
|
'parents_tags' => DeepPreloader::Spec.new(
|
132
131
|
'tag' => DeepPreloader::PolymorphicSpec.new(
|
@@ -157,8 +156,7 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
157
156
|
|
158
157
|
|
159
158
|
def test_serialize
|
160
|
-
view, refs = serialize_with_references(ParentView.new(@parent1)
|
161
|
-
serialize_context: context_with(:tags))
|
159
|
+
view, refs = serialize_with_references(ParentView.new(@parent1))
|
162
160
|
|
163
161
|
tag_data = view['tags'].map { |hash| refs[hash['_ref']] }
|
164
162
|
assert_equal([{ 'id' => @tag_a1.id, '_type' => 'TagA', '_version' => 1, 'name' => 'tag A1' },
|
@@ -188,7 +186,7 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
188
186
|
end
|
189
187
|
|
190
188
|
def test_reordering_swap_type
|
191
|
-
alter_by_view!(ParentView, @parent1
|
189
|
+
alter_by_view!(ParentView, @parent1) do |view, refs|
|
192
190
|
t1, t2, t3, t4 = view['tags']
|
193
191
|
view['tags'] = [t3, t2, t1, t4]
|
194
192
|
end
|
@@ -223,8 +221,9 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
223
221
|
end
|
224
222
|
|
225
223
|
define_viewmodel do
|
224
|
+
root!
|
226
225
|
attributes :name
|
227
|
-
association :tags,
|
226
|
+
association :tags, through: :parents_tags, through_order_attr: :position, viewmodels: [TagAView, TagBView], as: :something_else
|
228
227
|
end
|
229
228
|
end
|
230
229
|
|
@@ -244,12 +243,10 @@ class ViewModel::ActiveRecord::HasManyThroughPolyTest < ActiveSupport::TestCase
|
|
244
243
|
# Compare to non-polymorphic, which will also load the tags
|
245
244
|
deps = root_updates.first.preload_dependencies
|
246
245
|
assert_equal(DeepPreloader::Spec.new('parents_tags' => DeepPreloader::Spec.new('tag' => DeepPreloader::PolymorphicSpec.new)), deps)
|
247
|
-
assert_equal({ 'something_else' => {} }, root_updates.first.updated_associations)
|
248
246
|
end
|
249
247
|
|
250
|
-
|
251
248
|
def test_renamed_roundtrip
|
252
|
-
context = ParentView.new_serialize_context
|
249
|
+
context = ParentView.new_serialize_context
|
253
250
|
alter_by_view!(ParentView, @parent, serialize_context: context) do |view, refs|
|
254
251
|
assert_equal({refs.keys.first => { 'id' => @parent.parents_tags.first.tag.id,
|
255
252
|
'_type' => 'TagA',
|
@@ -19,8 +19,9 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
19
19
|
end
|
20
20
|
|
21
21
|
define_viewmodel do
|
22
|
+
root!
|
22
23
|
attributes :name
|
23
|
-
association :tags,
|
24
|
+
association :tags, through: :parents_tags, through_order_attr: :position
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
@@ -40,6 +41,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
40
41
|
end
|
41
42
|
|
42
43
|
define_viewmodel do
|
44
|
+
root!
|
43
45
|
attributes :name
|
44
46
|
if use_childtag
|
45
47
|
associations :child_tags
|
@@ -91,10 +93,6 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
91
93
|
self.class.build_join_table_model(self)
|
92
94
|
end
|
93
95
|
|
94
|
-
private def context_with(*args)
|
95
|
-
ParentView.new_serialize_context(include: args)
|
96
|
-
end
|
97
|
-
|
98
96
|
def setup
|
99
97
|
super
|
100
98
|
|
@@ -108,7 +106,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
108
106
|
end
|
109
107
|
|
110
108
|
def test_loading_batching
|
111
|
-
context =
|
109
|
+
context = ParentView.new_serialize_context
|
112
110
|
log_queries do
|
113
111
|
parent_views = ParentView.load(serialize_context: context)
|
114
112
|
serialize(parent_views, serialize_context: context)
|
@@ -121,13 +119,13 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
121
119
|
def test_roundtrip
|
122
120
|
# Objects are serialized to a view and deserialized, and should not be different when complete.
|
123
121
|
|
124
|
-
alter_by_view!(ParentView, @parent1
|
122
|
+
alter_by_view!(ParentView, @parent1) {}
|
125
123
|
assert_equal('p1', @parent1.name)
|
126
124
|
assert_equal([@tag1, @tag2], @parent1.parents_tags.order(:position).map(&:tag))
|
127
125
|
end
|
128
126
|
|
129
127
|
def test_eager_includes
|
130
|
-
includes = ParentView.eager_includes
|
128
|
+
includes = ParentView.eager_includes
|
131
129
|
assert_equal(DeepPreloader::Spec.new('parents_tags' => DeepPreloader::Spec.new('tag' => DeepPreloader::Spec.new)), includes)
|
132
130
|
end
|
133
131
|
|
@@ -150,21 +148,8 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
150
148
|
'mentioning tags and child_tags causes through association loading')
|
151
149
|
end
|
152
150
|
|
153
|
-
def test_updated_associations
|
154
|
-
root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes(
|
155
|
-
[{ '_type' => 'Parent',
|
156
|
-
'tags' => [{ '_ref' => 'r1' }] }],
|
157
|
-
{ 'r1' => { '_type' => 'Tag', } })
|
158
|
-
|
159
|
-
assert_equal({ 'tags' => {} },
|
160
|
-
root_updates.first.updated_associations,
|
161
|
-
'mentioning tags causes through association loading')
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
151
|
def test_serialize
|
166
|
-
view, refs = serialize_with_references(ParentView.new(@parent1)
|
167
|
-
serialize_context: context_with(:tags))
|
152
|
+
view, refs = serialize_with_references(ParentView.new(@parent1))
|
168
153
|
|
169
154
|
tag_data = view['tags'].map { |hash| refs[hash['_ref']] }
|
170
155
|
assert_equal([{ 'id' => @tag1.id, '_type' => 'Tag', '_version' => 1, 'name' => 'tag1' },
|
@@ -198,7 +183,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
198
183
|
end
|
199
184
|
|
200
185
|
def test_reordering
|
201
|
-
pv, ctx = alter_by_view!(ParentView, @parent1
|
186
|
+
pv, ctx = alter_by_view!(ParentView, @parent1) do |view, _refs|
|
202
187
|
view['tags'].reverse!
|
203
188
|
end
|
204
189
|
|
@@ -211,7 +196,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
211
196
|
|
212
197
|
def test_child_edit_doesnt_editcheck_parent
|
213
198
|
# editing child doesn't edit check parent
|
214
|
-
pv, d_context = alter_by_view!(ParentView, @parent1
|
199
|
+
pv, d_context = alter_by_view!(ParentView, @parent1) do |view, refs|
|
215
200
|
refs[view['tags'][0]["_ref"]]["name"] = "changed"
|
216
201
|
end
|
217
202
|
|
@@ -223,7 +208,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
223
208
|
end
|
224
209
|
|
225
210
|
def test_child_reordering_editchecks_parent
|
226
|
-
pv, d_context = alter_by_view!(ParentView, @parent1
|
211
|
+
pv, d_context = alter_by_view!(ParentView, @parent1) do |view, _refs|
|
227
212
|
view['tags'].reverse!
|
228
213
|
end
|
229
214
|
|
@@ -232,7 +217,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
232
217
|
end
|
233
218
|
|
234
219
|
def test_child_deletion_editchecks_parent
|
235
|
-
pv, d_context = alter_by_view!(ParentView, @parent1
|
220
|
+
pv, d_context = alter_by_view!(ParentView, @parent1) do |view, refs|
|
236
221
|
removed = view['tags'].pop['_ref']
|
237
222
|
refs.delete(removed)
|
238
223
|
end
|
@@ -242,7 +227,7 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
242
227
|
end
|
243
228
|
|
244
229
|
def test_child_addition_editchecks_parent
|
245
|
-
pv, d_context = alter_by_view!(ParentView, @parent1
|
230
|
+
pv, d_context = alter_by_view!(ParentView, @parent1) do |view, refs|
|
246
231
|
view['tags'] << { '_ref' => 't_new' }
|
247
232
|
refs['t_new'] = { '_type' => 'Tag', 'name' => 'newest tag' }
|
248
233
|
end
|
@@ -617,8 +602,9 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
617
602
|
end
|
618
603
|
|
619
604
|
define_viewmodel do
|
605
|
+
root!
|
620
606
|
attributes :name
|
621
|
-
association :tags,
|
607
|
+
association :tags, through: :parents_tags, through_order_attr: :position, as: :something_else
|
622
608
|
end
|
623
609
|
end
|
624
610
|
|
@@ -638,11 +624,10 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
638
624
|
root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes([{ '_type' => 'Parent', 'something_else' => [] }])
|
639
625
|
assert_equal(DeepPreloader::Spec.new('parents_tags' => DeepPreloader::Spec.new('tag' => DeepPreloader::Spec.new)),
|
640
626
|
root_updates.first.preload_dependencies)
|
641
|
-
assert_equal({ 'something_else' => {} }, root_updates.first.updated_associations)
|
642
627
|
end
|
643
628
|
|
644
629
|
def test_renamed_roundtrip
|
645
|
-
context = ParentView.new_serialize_context
|
630
|
+
context = ParentView.new_serialize_context
|
646
631
|
alter_by_view!(ParentView, @parent, serialize_context: context) do |view, refs|
|
647
632
|
assert_equal({refs.keys.first => { 'id' => @parent.parents_tags.first.tag.id,
|
648
633
|
'_type' => 'Tag',
|
@@ -703,34 +688,6 @@ class ViewModel::ActiveRecord::HasManyThroughTest < ActiveSupport::TestCase
|
|
703
688
|
root_updates.first.preload_dependencies,
|
704
689
|
'mentioning tags and child_tags in functional update value causes through association loading, ' \
|
705
690
|
'excluding shared')
|
706
|
-
|
707
|
-
end
|
708
|
-
|
709
|
-
def test_updated_associations
|
710
|
-
root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes(
|
711
|
-
[{ '_type' => 'Parent',
|
712
|
-
'tags' => [{ '_ref' => 'r1' }] }],
|
713
|
-
{ 'r1' => { '_type' => 'Tag', 'child_tags' => [] } })
|
714
|
-
|
715
|
-
assert_equal({ 'tags' => { } },
|
716
|
-
root_updates.first.updated_associations,
|
717
|
-
'mentioning tags and child_tags causes through association loading, excluding shared')
|
718
|
-
end
|
719
|
-
|
720
|
-
def test_updated_associations_functional
|
721
|
-
fupdate = build_fupdate do
|
722
|
-
append([{ '_ref' => 'r1' }])
|
723
|
-
end
|
724
|
-
|
725
|
-
root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes(
|
726
|
-
[{ '_type' => 'Parent',
|
727
|
-
'tags' => fupdate }],
|
728
|
-
{ 'r1' => { '_type' => 'Tag', 'child_tags' => [] } })
|
729
|
-
|
730
|
-
assert_equal({ 'tags' => { } },
|
731
|
-
root_updates.first.updated_associations,
|
732
|
-
'mentioning tags and child_tags in functional_update causes through association loading, ' \
|
733
|
-
'excluding shared')
|
734
691
|
end
|
735
692
|
end
|
736
693
|
end
|