iknow_view_models 2.10.1 → 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.
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
@@ -1,5 +1,6 @@
1
1
  require_relative "../../../helpers/arvm_test_utilities.rb"
2
2
  require_relative "../../../helpers/arvm_test_models.rb"
3
+ require_relative '../../../helpers/viewmodel_spec_helpers.rb'
3
4
 
4
5
  require "minitest/autorun"
5
6
 
@@ -8,80 +9,41 @@ require "view_model/active_record"
8
9
  class ViewModel::ActiveRecord::HasOneTest < ActiveSupport::TestCase
9
10
  include ARVMTestUtilities
10
11
 
11
- def self.build_target(arvm_test_case)
12
- arvm_test_case.build_viewmodel(:Target) do
13
- define_schema do |t|
14
- t.string :text
15
- t.references :parent, foreign_key: true
16
- end
17
-
18
- define_model do
19
- belongs_to :parent, inverse_of: :target
20
- end
21
-
22
- define_viewmodel do
23
- attributes :text
24
- end
25
- end
26
- end
27
-
28
-
29
- def self.build_parent(arvm_test_case)
30
- arvm_test_case.build_viewmodel(:Parent) do
31
- define_schema do |t|
32
- t.string :name
33
- end
34
-
35
- define_model do
36
- has_one :target, dependent: :destroy, inverse_of: :parent
37
- end
38
-
39
- define_viewmodel do
40
- attributes :name
41
- associations :target
42
- end
43
- end
44
- end
45
-
46
- def before_all
47
- super
48
-
49
- self.class.build_parent(self)
50
- self.class.build_target(self)
51
- end
12
+ extend Minitest::Spec::DSL
13
+ include ViewModelSpecHelpers::ParentAndHasOneChild
52
14
 
53
15
  def setup
54
16
  super
55
17
 
56
- # TODO make a `has_list?` that allows a parent to set all children as an array
57
- @parent1 = Parent.new(name: "p1",
58
- target: Target.new(text: "p1t"))
59
- @parent1.save!
18
+ # TODO make a `has_list?` that allows a model to set all children as an array
19
+ @model1 = model_class.new(name: "p1",
20
+ child: child_model_class.new(name: "p1t"))
21
+ @model1.save!
60
22
 
61
- @parent2 = Parent.new(name: "p2",
62
- target: Target.new(text: "p2t"))
23
+ @model2 = model_class.new(name: "p2",
24
+ child: child_model_class.new(name: "p2t"))
63
25
 
64
- @parent2.save!
26
+ @model2.save!
65
27
 
66
28
  enable_logging!
67
29
  end
68
30
 
69
31
  def test_loading_batching
70
32
  log_queries do
71
- serialize(ParentView.load)
33
+ serialize(ModelView.load)
72
34
  end
73
- assert_equal(['Parent Load', 'Target Load'],
35
+ assert_equal(['Model Load', 'Child Load'],
74
36
  logged_load_queries)
75
37
  end
76
38
 
77
39
  def test_create_from_view
78
40
  view = {
79
- "_type" => "Parent",
41
+ "_type" => "Model",
80
42
  "name" => "p",
81
- "target" => { "_type" => "Target", "text" => "t" },
43
+ "child" => { "_type" => "Child", "name" => "t" },
82
44
  }
83
45
 
84
- pv = ParentView.deserialize_from_view(view)
46
+ pv = ModelView.deserialize_from_view(view)
85
47
  p = pv.model
86
48
 
87
49
  assert(!p.changed?)
@@ -90,192 +52,383 @@ class ViewModel::ActiveRecord::HasOneTest < ActiveSupport::TestCase
90
52
  assert_equal("p", p.name)
91
53
 
92
54
 
93
- assert(p.target.present?)
94
- assert_equal("t", p.target.text)
55
+ assert(p.child.present?)
56
+ assert_equal("t", p.child.name)
95
57
  end
96
58
 
97
59
  def test_serialize_view
98
- view, _refs = serialize_with_references(ParentView.new(@parent1))
99
- assert_equal({ "_type" => "Parent",
60
+ view, _refs = serialize_with_references(ModelView.new(@model1))
61
+ assert_equal({ "_type" => "Model",
100
62
  "_version" => 1,
101
- "id" => @parent1.id,
102
- "name" => @parent1.name,
103
- "target" => { "_type" => "Target",
63
+ "id" => @model1.id,
64
+ "name" => @model1.name,
65
+ "child" => { "_type" => "Child",
104
66
  "_version" => 1,
105
- "id" => @parent1.target.id,
106
- "text" => @parent1.target.text } },
67
+ "id" => @model1.child.id,
68
+ "name" => @model1.child.name } },
107
69
  view)
108
70
  end
109
71
 
110
72
  def test_swap_has_one
111
- @parent1.update(target: t1 = Target.new)
112
- @parent2.update(target: t2 = Target.new)
73
+ @model1.update(child: t1 = Child.new)
74
+ @model2.update(child: t2 = Child.new)
113
75
 
114
76
  deserialize_context = ViewModelBase.new_deserialize_context
115
77
 
116
- ParentView.deserialize_from_view(
117
- [update_hash_for(ParentView, @parent1) { |p| p['target'] = update_hash_for(TargetView, t2) },
118
- update_hash_for(ParentView, @parent2) { |p| p['target'] = update_hash_for(TargetView, t1) }],
78
+ ModelView.deserialize_from_view(
79
+ [update_hash_for(ModelView, @model1) { |p| p['child'] = update_hash_for(ChildView, t2) },
80
+ update_hash_for(ModelView, @model2) { |p| p['child'] = update_hash_for(ChildView, t1) }],
119
81
  deserialize_context: deserialize_context)
120
82
 
121
- assert_equal(Set.new([ViewModel::Reference.new(ParentView, @parent1.id),
122
- ViewModel::Reference.new(ParentView, @parent2.id)]),
83
+ assert_equal(Set.new([ViewModel::Reference.new(ModelView, @model1.id),
84
+ ViewModel::Reference.new(ModelView, @model2.id)]),
123
85
  deserialize_context.valid_edit_refs.to_set)
124
86
 
125
- @parent1.reload
126
- @parent2.reload
87
+ @model1.reload
88
+ @model2.reload
127
89
 
128
- assert_equal(@parent1.target, t2)
129
- assert_equal(@parent2.target, t1)
90
+ assert_equal(@model1.child, t2)
91
+ assert_equal(@model2.child, t1)
130
92
  end
131
93
 
132
94
  def test_has_one_create_nil
133
- view = { '_type' => 'Parent', 'name' => 'p', 'target' => nil }
134
- pv = ParentView.deserialize_from_view(view)
135
- assert_nil(pv.model.target)
95
+ view = { '_type' => 'Model', 'name' => 'p', 'child' => nil }
96
+ pv = ModelView.deserialize_from_view(view)
97
+ assert_nil(pv.model.child)
136
98
  end
137
99
 
138
100
  def test_has_one_create
139
- @parent1.update(target: nil)
101
+ @model1.update(child: nil)
140
102
 
141
- alter_by_view!(ParentView, @parent1) do |view, refs|
142
- view['target'] = { '_type' => 'Target', 'text' => 't' }
103
+ alter_by_view!(ModelView, @model1) do |view, refs|
104
+ view['child'] = { '_type' => 'Child', 'name' => 't' }
143
105
  end
144
106
 
145
- assert_equal('t', @parent1.target.text)
107
+ assert_equal('t', @model1.child.name)
146
108
  end
147
109
 
148
110
  def test_has_one_update
149
- alter_by_view!(ParentView, @parent1) do |view, refs|
150
- view['target']['text'] = "hello"
111
+ alter_by_view!(ModelView, @model1) do |view, refs|
112
+ view['child']['name'] = "hello"
151
113
  end
152
114
 
153
- assert_equal('hello', @parent1.target.text)
115
+ assert_equal('hello', @model1.child.name)
154
116
  end
155
117
 
156
118
  def test_has_one_destroy
157
- old_target = @parent1.target
158
- alter_by_view!(ParentView, @parent1) do |view, refs|
159
- view['target'] = nil
119
+ old_child = @model1.child
120
+ alter_by_view!(ModelView, @model1) do |view, refs|
121
+ view['child'] = nil
160
122
  end
161
- assert(Target.where(id: old_target.id).blank?)
123
+ assert(Child.where(id: old_child.id).blank?)
162
124
  end
163
125
 
164
126
  def test_has_one_move_and_replace
165
- old_parent1_target = @parent1.target
166
- old_parent2_target = @parent2.target
127
+ old_model1_child = @model1.child
128
+ old_model2_child = @model2.child
167
129
 
168
- alter_by_view!(ParentView, [@parent1, @parent2]) do |(p1, p2), refs|
169
- p2['target'] = p1['target']
170
- p1['target'] = nil
130
+ alter_by_view!(ModelView, [@model1, @model2]) do |(p1, p2), refs|
131
+ p2['child'] = p1['child']
132
+ p1['child'] = nil
171
133
  end
172
134
 
173
- assert(@parent1.target.blank?)
174
- assert_equal(old_parent1_target, @parent2.target)
175
- assert(Target.where(id: old_parent2_target).blank?)
135
+ assert(@model1.child.blank?)
136
+ assert_equal(old_model1_child, @model2.child)
137
+ assert(Child.where(id: old_model2_child).blank?)
176
138
  end
177
139
 
178
140
  def test_has_one_cannot_duplicate_unreleased_child
179
- # p2 shouldn't be able to copy p1's target
141
+ # p2 shouldn't be able to copy p1's child
180
142
  assert_raises(ViewModel::DeserializationError::DuplicateNodes) do
181
- alter_by_view!(ParentView, [@parent1, @parent2]) do |(p1, p2), _refs|
182
- p2['target'] = p1['target'].dup
143
+ alter_by_view!(ModelView, [@model1, @model2]) do |(p1, p2), _refs|
144
+ p2['child'] = p1['child'].dup
183
145
  end
184
146
  end
185
147
  end
186
148
 
187
149
  def test_has_one_cannot_duplicate_implicitly_unreleased_child
188
- # p2 shouldn't be able to copy p1's target, even when p1 doesn't explicitly
150
+ # p2 shouldn't be able to copy p1's child, even when p1 doesn't explicitly
189
151
  # specify the association
190
152
  assert_raises(ViewModel::DeserializationError::ParentNotFound) do
191
- alter_by_view!(ParentView, [@parent1, @parent2]) do |(p1, p2), _refs|
192
- p2['target'] = p1['target']
193
- p1.delete('target')
153
+ alter_by_view!(ModelView, [@model1, @model2]) do |(p1, p2), _refs|
154
+ p2['child'] = p1['child']
155
+ p1.delete('child')
194
156
  end
195
157
  end
196
158
  end
197
159
 
198
160
  def test_has_one_cannot_take_from_outside_tree
199
- t3 = Parent.create(target: Target.new(text: 'hi')).target
161
+ t3 = Model.create(child: Child.new(name: 'hi')).child
200
162
 
201
163
  assert_raises(ViewModel::DeserializationError::ParentNotFound) do
202
- alter_by_view!(ParentView, [@parent1]) do |(p1), _refs|
203
- p1['target'] = update_hash_for(TargetView, t3)
164
+ alter_by_view!(ModelView, [@model1]) do |(p1), _refs|
165
+ p1['child'] = update_hash_for(ChildView, t3)
204
166
  end
205
167
  end
206
168
  end
207
169
 
208
- def test_has_one_cannot_take_unparented_from_outside_tree
209
- t3 = Target.create(text: 'hi') # no parent
170
+ def test_has_one_cannot_take_unmodeled_from_outside_tree
171
+ t3 = Child.create(name: 'hi') # no model
210
172
 
211
173
  assert_raises(ViewModel::DeserializationError::ParentNotFound) do
212
- alter_by_view!(ParentView, @parent1) do |p1, _refs|
213
- p1['target'] = update_hash_for(TargetView, t3)
174
+ alter_by_view!(ModelView, @model1) do |p1, _refs|
175
+ p1['child'] = update_hash_for(ChildView, t3)
214
176
  end
215
177
  end
216
178
  end
217
179
 
218
180
  def test_bad_single_association
219
181
  view = {
220
- "_type" => "Parent",
221
- "target" => []
182
+ "_type" => "Model",
183
+ "child" => []
222
184
  }
223
185
  ex = assert_raises(ViewModel::DeserializationError::InvalidSyntax) do
224
- ParentView.deserialize_from_view(view)
186
+ ModelView.deserialize_from_view(view)
225
187
  end
226
188
  assert_match(/not an object/, ex.message)
227
189
  end
228
190
 
191
+ describe 'owned reference child' do
192
+ def child_attributes
193
+ super.merge(viewmodel: ->(v) { root! })
194
+ end
229
195
 
230
- class RenameTest < ActiveSupport::TestCase
231
- include ARVMTestUtilities
196
+ def new_model
197
+ model_class.new(name: 'm1', child: child_model_class.new(name: 'c1'))
198
+ end
232
199
 
233
- def before_all
234
- super
200
+ it 'makes a reference association' do
201
+ assert(subject_association.referenced?)
202
+ end
235
203
 
236
- build_viewmodel(:Parent) do
237
- define_schema do |t|
238
- t.string :name
204
+ it 'makes an owned association' do
205
+ assert(subject_association.owned?)
206
+ end
207
+
208
+ it 'loads and batches' do
209
+ create_model!
210
+
211
+ log_queries do
212
+ serialize(ModelView.load)
213
+ end
214
+
215
+ assert_equal(['Model Load', 'Child Load'], logged_load_queries)
216
+ end
217
+
218
+ it 'serializes' do
219
+ model = create_model!
220
+ view, refs = serialize_with_references(ModelView.new(model))
221
+ child1_ref = refs.detect { |_, v| v['_type'] == 'Child' }.first
222
+
223
+ assert_equal({ child1_ref => { '_type' => 'Child',
224
+ '_version' => 1,
225
+ 'id' => model.child.id,
226
+ 'name' => model.child.name } },
227
+ refs)
228
+
229
+ assert_equal({ '_type' => 'Model',
230
+ '_version' => 1,
231
+ 'id' => model.id,
232
+ 'name' => model.name,
233
+ 'child' => { '_ref' => child1_ref } },
234
+ view)
235
+ end
236
+
237
+ it 'creates from view' do
238
+ view = {
239
+ '_type' => 'Model',
240
+ 'name' => 'p',
241
+ 'child' => { '_ref' => 'r1' },
242
+ }
243
+
244
+ refs = {
245
+ 'r1' => { '_type' => 'Child', 'name' => 'newkid' },
246
+ }
247
+
248
+ pv = ModelView.deserialize_from_view(view, references: refs)
249
+ p = pv.model
250
+
251
+ assert(!p.changed?)
252
+ assert(!p.new_record?)
253
+
254
+ assert_equal('p', p.name)
255
+
256
+ assert(p.child.present?)
257
+ assert_equal('newkid', p.child.name)
258
+ end
259
+
260
+ it 'updates' do
261
+ model = create_model!
262
+
263
+ alter_by_view!(ModelView, model) do |view, refs|
264
+ ref = view['child']['_ref']
265
+ refs[ref]['name'] = 'newchildname'
266
+ end
267
+
268
+ assert_equal('newchildname', model.child.name)
269
+ end
270
+
271
+ describe 'without a child' do
272
+ let(:new_model) {
273
+ model_class.new(name: 'm1', child: nil)
274
+ }
275
+
276
+ it 'can add a child' do
277
+ model = create_model!
278
+
279
+ alter_by_view!(ModelView, model) do |view, refs|
280
+ view['child'] = { '_ref' => 'ref1' }
281
+ refs['ref1'] = {
282
+ '_type' => 'Child',
283
+ 'name' => 'newchildname',
284
+ }
239
285
  end
240
286
 
241
- define_model do
242
- has_one :target, dependent: :destroy, inverse_of: :parent
287
+ assert(model.child.present?)
288
+ assert_equal('newchildname', model.child.name)
289
+ end
290
+ end
291
+
292
+ it 'replaces a child with a new child' do
293
+ model = create_model!
294
+ old_child = model.child
295
+
296
+ alter_by_view!(ModelView, model) do |view, refs|
297
+ ref = view['child']['_ref']
298
+ refs[ref] = { '_type' => 'Child', 'name' => 'newchildname' }
299
+ end
300
+ model.reload
301
+
302
+ assert_equal('newchildname', model.child.name)
303
+ refute_equal(old_child, model.child)
304
+ assert(Child.where(id: old_child.id).blank?)
305
+ end
306
+
307
+ it 'takes a released child from another parent' do
308
+ model1 = create_model!
309
+ model2 = create_model!
310
+
311
+ old_child1 = model1.child
312
+ old_child2 = model2.child
313
+
314
+ alter_by_view!(ModelView, [model1, model2]) do |(view1, view2), refs|
315
+ ref1 = view1['child']['_ref']
316
+ ref2 = view2['child']['_ref']
317
+ refs.delete(ref1)
318
+ view1['child'] = { '_ref' => ref2 }
319
+ view2['child'] = nil
320
+ end
321
+
322
+ assert_equal(model1.child, old_child2)
323
+ assert_nil(model2.child)
324
+ assert(Child.where(id: old_child1.id).blank?)
325
+ end
326
+
327
+ it 'prevents taking an unreleased reference out-of-tree' do
328
+ model1 = create_model!
329
+ child2 = Child.create!(name: 'dummy')
330
+
331
+ assert_raises(ViewModel::DeserializationError::ParentNotFound) do
332
+ alter_by_view!(ModelView, model1) do |view, refs|
333
+ refs.clear
334
+ view['child']['_ref'] = 'r1'
335
+ refs['r1'] = { '_type' => 'Child', 'id' => child2.id }
243
336
  end
337
+ end
338
+ end
244
339
 
245
- define_viewmodel do
246
- attributes :name
247
- association :target, as: :something_else
340
+ it 'prevents taking an unreleased reference in-tree' do
341
+ model1 = create_model!
342
+ model2 = create_model!
343
+
344
+ assert_raises(ViewModel::DeserializationError::DuplicateOwner) do
345
+ alter_by_view!(ModelView, [model1, model2]) do |(view1, view2), refs|
346
+ refs.delete(view1['child']['_ref'])
347
+ view1['child']['_ref'] = view2['child']['_ref']
248
348
  end
249
349
  end
350
+ end
351
+
352
+ it 'prevents two parents taking the same new reference' do
353
+ model1 = create_model!
354
+ model2 = create_model!
355
+
356
+ assert_raises(ViewModel::DeserializationError::DuplicateOwner) do
357
+ alter_by_view!(ModelView, [model1, model2]) do |(view1, view2), refs|
358
+ refs.clear
359
+ refs['ref1'] = { '_type' => 'Child', 'name' => 'new' }
360
+ view1['child']['_ref'] = 'ref1'
361
+ view2['child']['_ref'] = 'ref1'
362
+ end
363
+ end
364
+ end
365
+
366
+ it 'swaps children' do
367
+ model1 = create_model!
368
+ model2 = create_model!
369
+
370
+ old_child1 = model1.child
371
+ old_child2 = model2.child
372
+
373
+ alter_by_view!(ModelView, [model1, model2]) do |(view1, view2), _refs|
374
+ ref1 = view1['child']
375
+ ref2 = view2['child']
376
+ view1['child'] = ref2
377
+ view2['child'] = ref1
378
+ end
379
+
380
+ assert_equal(model1.child, old_child2)
381
+ assert_equal(model2.child, old_child1)
382
+ end
383
+
384
+ it 'deletes a child' do
385
+ model = create_model!
386
+ old_child = model.child
387
+
388
+ alter_by_view!(ModelView, model) do |view, refs|
389
+ refs.clear
390
+ view['child'] = nil
391
+ end
392
+
393
+ assert_nil(model.child)
394
+ assert(Child.where(id: old_child.id).blank?)
395
+ end
396
+
397
+ it 'eager includes' do
398
+ includes = viewmodel_class.eager_includes
399
+ assert_equal(DeepPreloader::Spec.new('child' => DeepPreloader::Spec.new), includes)
400
+ end
401
+ end
250
402
 
251
- ViewModel::ActiveRecord::HasOneTest.build_target(self)
403
+ describe 'renaming associations' do
404
+ def subject_association_features
405
+ { as: :something_else }
252
406
  end
253
407
 
254
408
  def setup
255
409
  super
256
410
 
257
- @parent = Parent.create(target: Target.new(text: 'target text'))
411
+ @model = model_class.create(child: child_model_class.new(name: 'child name'))
258
412
 
259
413
  enable_logging!
260
414
  end
261
415
 
262
416
  def test_dependencies
263
- root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes([{ '_type' => 'Parent', 'something_else' => nil }])
264
- assert_equal(DeepPreloader::Spec.new('target' => DeepPreloader::Spec.new), root_updates.first.preload_dependencies)
265
- assert_equal({ 'something_else' => {} }, root_updates.first.updated_associations)
417
+ root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes([{ '_type' => 'Model', 'something_else' => nil }])
418
+ assert_equal(DeepPreloader::Spec.new('child' => DeepPreloader::Spec.new), root_updates.first.preload_dependencies)
266
419
  end
267
420
 
268
421
  def test_renamed_roundtrip
269
- alter_by_view!(ParentView, @parent) do |view, refs|
270
- assert_equal({ 'id' => @parent.target.id,
271
- '_type' => 'Target',
422
+ alter_by_view!(ModelView, @model) do |view, refs|
423
+ assert_equal({ 'id' => @model.child.id,
424
+ '_type' => 'Child',
272
425
  '_version' => 1,
273
- 'text' => 'target text' },
426
+ 'name' => 'child name' },
274
427
  view['something_else'])
275
- view['something_else']['text'] = 'target new text'
428
+ view['something_else']['name'] = 'child new name'
276
429
  end
277
430
 
278
- assert_equal('target new text', @parent.target.text)
431
+ assert_equal('child new name', @model.child.name)
279
432
  end
280
433
  end
281
434
 
@@ -299,7 +299,6 @@ module ViewModel::ActiveRecord::PolyTest
299
299
  def test_dependencies
300
300
  root_updates, _ref_updates = ViewModel::ActiveRecord::UpdateData.parse_hashes([{ '_type' => 'Parent', 'something_else' => nil }])
301
301
  assert_equal(DeepPreloader::Spec.new('poly' => DeepPreloader::PolymorphicSpec.new), root_updates.first.preload_dependencies)
302
- assert_equal({ 'something_else' => {} }, root_updates.first.updated_associations)
303
302
  end
304
303
 
305
304
  def test_renamed_roundtrip