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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +119 -0
- data/.travis.yml +31 -0
- data/Appraisals +6 -16
- data/gemfiles/{rails_7_0.gemfile → rails_6_0_beta.gemfile} +2 -2
- data/iknow_view_models.gemspec +3 -5
- 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/callbacks.rb +2 -2
- 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/test_helpers/arvm_builder.rb +2 -4
- data/lib/view_model/traversal_context.rb +2 -2
- data/lib/view_model.rb +21 -13
- data/shell.nix +1 -1
- data/test/helpers/arvm_test_models.rb +4 -12
- data/test/helpers/arvm_test_utilities.rb +6 -0
- data/test/helpers/controller_test_helpers.rb +6 -6
- 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 +11 -5
- 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 +15 -25
- data/.github/workflows/gem-push.yml +0 -31
- data/.github/workflows/test.yml +0 -65
- data/gemfiles/rails_6_0.gemfile +0 -9
- data/gemfiles/rails_6_1.gemfile +0 -9
- 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
|