iknow_view_models 3.2.0 → 3.2.1

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +13 -0
  3. data/Appraisals +6 -6
  4. data/Rakefile +5 -5
  5. data/gemfiles/rails_5_2.gemfile +5 -5
  6. data/gemfiles/rails_6_0.gemfile +5 -5
  7. data/iknow_view_models.gemspec +40 -39
  8. data/lib/iknow_view_models.rb +9 -7
  9. data/lib/iknow_view_models/version.rb +1 -1
  10. data/lib/view_model.rb +17 -14
  11. data/lib/view_model/access_control.rb +5 -2
  12. data/lib/view_model/access_control/composed.rb +10 -9
  13. data/lib/view_model/access_control/open.rb +2 -0
  14. data/lib/view_model/access_control/read_only.rb +2 -0
  15. data/lib/view_model/access_control/tree.rb +11 -6
  16. data/lib/view_model/access_control_error.rb +4 -1
  17. data/lib/view_model/active_record.rb +12 -11
  18. data/lib/view_model/active_record/association_data.rb +2 -1
  19. data/lib/view_model/active_record/association_manipulation.rb +6 -4
  20. data/lib/view_model/active_record/cache.rb +4 -2
  21. data/lib/view_model/active_record/collection_nested_controller.rb +3 -3
  22. data/lib/view_model/active_record/controller_base.rb +4 -1
  23. data/lib/view_model/active_record/nested_controller_base.rb +1 -0
  24. data/lib/view_model/active_record/update_context.rb +8 -6
  25. data/lib/view_model/active_record/update_data.rb +32 -30
  26. data/lib/view_model/active_record/update_operation.rb +17 -13
  27. data/lib/view_model/active_record/visitor.rb +0 -1
  28. data/lib/view_model/after_transaction_runner.rb +0 -1
  29. data/lib/view_model/callbacks.rb +3 -1
  30. data/lib/view_model/controller.rb +13 -3
  31. data/lib/view_model/deserialization_error.rb +15 -12
  32. data/lib/view_model/error.rb +12 -10
  33. data/lib/view_model/error_view.rb +3 -1
  34. data/lib/view_model/migration/no_path_error.rb +1 -0
  35. data/lib/view_model/migration/one_way_error.rb +1 -0
  36. data/lib/view_model/migration/unspecified_version_error.rb +1 -0
  37. data/lib/view_model/record.rb +11 -13
  38. data/lib/view_model/reference.rb +3 -1
  39. data/lib/view_model/references.rb +8 -5
  40. data/lib/view_model/registry.rb +1 -1
  41. data/lib/view_model/schemas.rb +9 -4
  42. data/lib/view_model/serialization_error.rb +4 -1
  43. data/lib/view_model/serialize_context.rb +4 -4
  44. data/lib/view_model/test_helpers.rb +8 -3
  45. data/lib/view_model/test_helpers/arvm_builder.rb +19 -14
  46. data/lib/view_model/traversal_context.rb +2 -1
  47. data/test/.rubocop.yml +14 -0
  48. data/test/helpers/arvm_test_models.rb +12 -9
  49. data/test/helpers/arvm_test_utilities.rb +5 -3
  50. data/test/helpers/controller_test_helpers.rb +31 -29
  51. data/test/helpers/match_enumerator.rb +1 -0
  52. data/test/helpers/query_logging.rb +2 -1
  53. data/test/helpers/test_access_control.rb +5 -3
  54. data/test/helpers/viewmodel_spec_helpers.rb +21 -20
  55. data/test/unit/view_model/access_control_test.rb +144 -144
  56. data/test/unit/view_model/active_record/alias_test.rb +15 -13
  57. data/test/unit/view_model/active_record/belongs_to_test.rb +40 -39
  58. data/test/unit/view_model/active_record/cache_test.rb +27 -26
  59. data/test/unit/view_model/active_record/cloner_test.rb +67 -63
  60. data/test/unit/view_model/active_record/controller_test.rb +37 -38
  61. data/test/unit/view_model/active_record/counter_test.rb +10 -9
  62. data/test/unit/view_model/active_record/customization_test.rb +59 -58
  63. data/test/unit/view_model/active_record/has_many_test.rb +112 -111
  64. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +15 -14
  65. data/test/unit/view_model/active_record/has_many_through_test.rb +33 -38
  66. data/test/unit/view_model/active_record/has_one_test.rb +37 -36
  67. data/test/unit/view_model/active_record/migration_test.rb +13 -13
  68. data/test/unit/view_model/active_record/namespacing_test.rb +19 -17
  69. data/test/unit/view_model/active_record/poly_test.rb +44 -45
  70. data/test/unit/view_model/active_record/shared_test.rb +30 -28
  71. data/test/unit/view_model/active_record/version_test.rb +9 -7
  72. data/test/unit/view_model/active_record_test.rb +72 -72
  73. data/test/unit/view_model/callbacks_test.rb +19 -15
  74. data/test/unit/view_model/controller_test.rb +4 -2
  75. data/test/unit/view_model/record_test.rb +92 -97
  76. data/test/unit/view_model/traversal_context_test.rb +4 -5
  77. data/test/unit/view_model_test.rb +18 -16
  78. metadata +7 -5
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'minitest/autorun'
2
4
  require 'minitest/unit'
3
5
  require 'minitest/hooks'
4
6
 
5
- require_relative '../../helpers/arvm_test_utilities.rb'
6
- require_relative '../../helpers/viewmodel_spec_helpers.rb'
7
+ require_relative '../../helpers/arvm_test_utilities'
8
+ require_relative '../../helpers/viewmodel_spec_helpers'
7
9
 
8
10
  require 'view_model'
9
11
  require 'view_model/controller'
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../helpers/test_access_control.rb"
3
+ require_relative '../../helpers/test_access_control'
4
4
 
5
- require "minitest/autorun"
5
+ require 'minitest/autorun'
6
6
  require 'minitest/unit'
7
7
 
8
- require "view_model"
9
- require "view_model/record"
8
+ require 'view_model'
9
+ require 'view_model/record'
10
10
 
11
11
  class ViewModel::RecordTest < ActiveSupport::TestCase
12
12
  using ViewModel::Utils::Collections
@@ -15,6 +15,7 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
15
15
  class TestDeserializeContext < ViewModel::DeserializeContext
16
16
  class SharedContext < ViewModel::DeserializeContext::SharedContext
17
17
  attr_reader :targets
18
+
18
19
  def initialize(targets: [], **rest)
19
20
  super(**rest)
20
21
  @targets = targets
@@ -26,16 +27,9 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
26
27
  end
27
28
 
28
29
  delegate :targets, to: :shared_context
29
-
30
- def initialize(**rest)
31
- super(**rest)
32
- end
33
30
  end
34
31
 
35
32
  class TestSerializeContext < ViewModel::SerializeContext
36
- def initialize(**rest)
37
- super(**rest)
38
- end
39
33
  end
40
34
 
41
35
  class TestViewModel < ViewModel::Record
@@ -79,7 +73,7 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
79
73
  # associations.
80
74
  self.unregistered = true
81
75
 
82
- self.view_name = "Model"
76
+ self.view_name = 'Model'
83
77
  self.model_class = mc
84
78
 
85
79
  attrs.each { |a, opts| attribute(a, **opts) }
@@ -90,8 +84,8 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
90
84
 
91
85
  let(:view_base) do
92
86
  {
93
- "_type" => "Model",
94
- "_version" => 1,
87
+ '_type' => 'Model',
88
+ '_version' => 1,
95
89
  }
96
90
  end
97
91
 
@@ -144,7 +138,7 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
144
138
  module CanDeserializeToNew
145
139
  def self.included(base)
146
140
  base.instance_eval do
147
- it "can deserialize to a new model" do
141
+ it 'can deserialize to a new model' do
148
142
  vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: create_context)
149
143
  assert_equal(default_model, vm.model)
150
144
  refute(default_model.equal?(vm.model))
@@ -159,7 +153,7 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
159
153
  module CanDeserializeToExisting
160
154
  def self.included(base)
161
155
  base.instance_eval do
162
- it "can deserialize to existing model with no changes" do
156
+ it 'can deserialize to existing model with no changes' do
163
157
  vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
164
158
  assert(default_model.equal?(vm.model))
165
159
 
@@ -172,7 +166,7 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
172
166
  module CanSerialize
173
167
  def self.included(base)
174
168
  base.instance_eval do
175
- it "can serialize to the expected view" do
169
+ it 'can serialize to the expected view' do
176
170
  h = viewmodel_class.new(default_model).to_hash
177
171
  assert_equal(default_view, h)
178
172
  end
@@ -180,44 +174,44 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
180
174
  end
181
175
  end
182
176
 
183
- describe "with simple attribute" do
177
+ describe 'with simple attribute' do
184
178
  let(:attributes) { { simple: {} } }
185
179
  include CanSerialize
186
180
  include CanDeserializeToNew
187
181
  include CanDeserializeToExisting
188
182
 
189
- it "can be updated" do
190
- new_view = default_view.merge("simple" => "changed")
183
+ it 'can be updated' do
184
+ new_view = default_view.merge('simple' => 'changed')
191
185
 
192
186
  vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
193
187
 
194
- assert(default_model.equal?(vm.model), "returned model was not the same")
195
- assert_equal("changed", default_model.simple)
188
+ assert(default_model.equal?(vm.model), 'returned model was not the same')
189
+ assert_equal('changed', default_model.simple)
196
190
  assert_edited(vm, changed_attributes: [:simple])
197
191
  end
198
192
 
199
- it "rejects unknown attributes" do
200
- view = default_view.merge("unknown" => "illegal")
193
+ it 'rejects unknown attributes' do
194
+ view = default_view.merge('unknown' => 'illegal')
201
195
  ex = assert_raises(ViewModel::DeserializationError::UnknownAttribute) do
202
196
  viewmodel_class.deserialize_from_view(view, deserialize_context: create_context)
203
197
  end
204
- assert_equal("unknown", ex.attribute)
198
+ assert_equal('unknown', ex.attribute)
205
199
  end
206
200
 
207
- it "edit checks when creating empty" do
201
+ it 'edit checks when creating empty' do
208
202
  vm = viewmodel_class.deserialize_from_view(view_base, deserialize_context: create_context)
209
- refute(default_model.equal?(vm.model), "returned model was the same")
203
+ refute(default_model.equal?(vm.model), 'returned model was the same')
210
204
  assert_edited(vm, new: true)
211
205
  end
212
206
  end
213
207
 
214
- describe "with validated simple attribute" do
208
+ describe 'with validated simple attribute' do
215
209
  let(:attributes) { { validated: {} } }
216
210
  let(:viewmodel_body) do
217
211
  ->(_x) do
218
212
  def validate!
219
- if validated == "naughty"
220
- raise ViewModel::DeserializationError::Validation.new("validated", "was naughty", nil, self.blame_reference)
213
+ if validated == 'naughty'
214
+ raise ViewModel::DeserializationError::Validation.new('validated', 'was naughty', nil, self.blame_reference)
221
215
  end
222
216
  end
223
217
  end
@@ -227,34 +221,34 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
227
221
  include CanDeserializeToNew
228
222
  include CanDeserializeToExisting
229
223
 
230
- it "rejects update when validation fails" do
231
- new_view = default_view.merge("validated" => "naughty")
224
+ it 'rejects update when validation fails' do
225
+ new_view = default_view.merge('validated' => 'naughty')
232
226
 
233
227
  ex = assert_raises(ViewModel::DeserializationError::Validation) do
234
228
  viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
235
229
  end
236
- assert_equal("validated", ex.attribute)
237
- assert_equal("was naughty", ex.reason)
230
+ assert_equal('validated', ex.attribute)
231
+ assert_equal('was naughty', ex.reason)
238
232
  end
239
233
  end
240
234
 
241
- describe "with renamed attribute" do
235
+ describe 'with renamed attribute' do
242
236
  let(:attributes) { { modelname: { as: :viewname } } }
243
- let(:default_model_values) { { modelname: "value" } }
244
- let(:default_view_values) { { viewname: "value" } }
237
+ let(:default_model_values) { { modelname: 'value' } }
238
+ let(:default_view_values) { { viewname: 'value' } }
245
239
 
246
240
  include CanSerialize
247
241
  include CanDeserializeToNew
248
242
  include CanDeserializeToExisting
249
243
 
250
- it "makes attributes available on their new names" do
251
- value(default_model.modelname).must_equal("value")
244
+ it 'makes attributes available on their new names' do
245
+ value(default_model.modelname).must_equal('value')
252
246
  vm = viewmodel_class.new(default_model)
253
- value(vm.viewname).must_equal("value")
247
+ value(vm.viewname).must_equal('value')
254
248
  end
255
249
  end
256
250
 
257
- describe "with formatted attribute" do
251
+ describe 'with formatted attribute' do
258
252
  let(:attributes) { { moment: { format: IknowParams::Serializer::Time } } }
259
253
  let(:moment) { 1.week.ago.change(usec: 0) }
260
254
  let(:default_model_values) { { moment: moment } }
@@ -264,8 +258,8 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
264
258
  include CanDeserializeToNew
265
259
  include CanDeserializeToExisting
266
260
 
267
- it "raises correctly on an unparseable value" do
268
- bad_view = default_view.tap { |v| v["moment"] = "not a timestamp" }
261
+ it 'raises correctly on an unparseable value' do
262
+ bad_view = default_view.tap { |v| v['moment'] = 'not a timestamp' }
269
263
  ex = assert_raises(ViewModel::DeserializationError::Validation) do
270
264
  viewmodel_class.deserialize_from_view(bad_view, deserialize_context: create_context)
271
265
  end
@@ -273,7 +267,7 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
273
267
  assert_match(/could not be deserialized because.*Time/, ex.detail)
274
268
  end
275
269
 
276
- it "raises correctly on an undeserializable value" do
270
+ it 'raises correctly on an undeserializable value' do
277
271
  bad_model = default_model.tap { |m| m.moment = 2.7 }
278
272
  ex = assert_raises(ViewModel::SerializationError) do
279
273
  viewmodel_class.new(bad_model).to_hash
@@ -282,40 +276,40 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
282
276
  end
283
277
  end
284
278
 
285
- describe "with read-only attribute" do
279
+ describe 'with read-only attribute' do
286
280
  let(:attributes) { { read_only: { read_only: true } } }
287
281
 
288
282
  include CanSerialize
289
283
  include CanDeserializeToExisting
290
284
 
291
- it "deserializes to new without the attribute" do
292
- new_view = default_view.tap { |v| v.delete("read_only") }
285
+ it 'deserializes to new without the attribute' do
286
+ new_view = default_view.tap { |v| v.delete('read_only') }
293
287
  vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: create_context)
294
288
  refute(default_model.equal?(vm.model))
295
289
  assert_nil(vm.model.read_only)
296
290
  assert_edited(vm, new: true)
297
291
  end
298
292
 
299
- it "rejects deserialize from new" do
293
+ it 'rejects deserialize from new' do
300
294
  ex = assert_raises(ViewModel::DeserializationError::ReadOnlyAttribute) do
301
295
  viewmodel_class.deserialize_from_view(default_view, deserialize_context: create_context)
302
296
  end
303
- assert_equal("read_only", ex.attribute)
297
+ assert_equal('read_only', ex.attribute)
304
298
  end
305
299
 
306
- it "rejects update if changed" do
307
- new_view = default_view.merge("read_only" => "written")
300
+ it 'rejects update if changed' do
301
+ new_view = default_view.merge('read_only' => 'written')
308
302
  ex = assert_raises(ViewModel::DeserializationError::ReadOnlyAttribute) do
309
303
  viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
310
304
  end
311
- assert_equal("read_only", ex.attribute)
305
+ assert_equal('read_only', ex.attribute)
312
306
  end
313
307
  end
314
308
 
315
- describe "with read-only write-once attribute" do
309
+ describe 'with read-only write-once attribute' do
316
310
  let(:attributes) { { write_once: { read_only: true, write_once: true } } }
317
311
  let(:model_body) do
318
- ->(x) do
312
+ ->(_x) do
319
313
  # For the purposes of testing, we assume a record is new and can be
320
314
  # written once to if write_once is nil. We will never write a nil.
321
315
  def new_record?
@@ -328,21 +322,21 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
328
322
  include CanDeserializeToNew
329
323
  include CanDeserializeToExisting
330
324
 
331
- it "rejects change to attribute" do
332
- new_view = default_view.merge("write_once" => "written")
325
+ it 'rejects change to attribute' do
326
+ new_view = default_view.merge('write_once' => 'written')
333
327
  ex = assert_raises(ViewModel::DeserializationError::ReadOnlyAttribute) do
334
328
  viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
335
329
  end
336
- assert_equal("write_once", ex.attribute)
330
+ assert_equal('write_once', ex.attribute)
337
331
  end
338
332
  end
339
333
 
340
- describe "with custom serialization" do
334
+ describe 'with custom serialization' do
341
335
  let(:attributes) { { overridden: {} } }
342
336
  let(:default_view_values) { { overridden: 10 } }
343
337
  let(:default_model_values) { { overridden: 5 } }
344
338
  let(:viewmodel_body) do
345
- ->(x) do
339
+ ->(_x) do
346
340
  def serialize_overridden(json, serialize_context:)
347
341
  json.overridden model.overridden.try { |o| o * 2 }
348
342
  end
@@ -359,12 +353,12 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
359
353
  include CanDeserializeToNew
360
354
  include CanDeserializeToExisting
361
355
 
362
- it "can be updated" do
363
- new_view = default_view.merge("overridden" => "20")
356
+ it 'can be updated' do
357
+ new_view = default_view.merge('overridden' => '20')
364
358
 
365
359
  vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
366
360
 
367
- assert(default_model.equal?(vm.model), "returned model was not the same")
361
+ assert(default_model.equal?(vm.model), 'returned model was not the same')
368
362
  assert_equal(10, default_model.overridden)
369
363
 
370
364
  assert_edited(vm, changed_attributes: [:overridden])
@@ -374,66 +368,68 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
374
368
  Nested = Struct.new(:member)
375
369
 
376
370
  class NestedView < TestViewModel
377
- self.view_name = "Nested"
371
+ self.view_name = 'Nested'
378
372
  self.model_class = Nested
379
373
  attribute :member
380
374
  end
381
375
 
382
- describe "with nested viewmodel" do
383
- let(:default_nested_model) { Nested.new("member") }
384
- let(:default_nested_view) { view_base.merge("_type" => "Nested", "member" => "member") }
376
+ describe 'with nested viewmodel' do
377
+ let(:default_nested_model) { Nested.new('member') }
378
+ let(:default_nested_view) { view_base.merge('_type' => 'Nested', 'member' => 'member') }
385
379
 
386
- let(:attributes) {{ simple: {}, nested: { using: NestedView } }}
380
+ let(:attributes) { { simple: {}, nested: { using: NestedView } } }
387
381
 
388
382
  let(:default_view_values) { { nested: default_nested_view } }
389
383
  let(:default_model_values) { { nested: default_nested_model } }
390
384
 
391
- let(:update_context) { TestDeserializeContext.new(targets: [default_model, default_nested_model],
392
- access_control: access_control) }
385
+ let(:update_context) do
386
+ TestDeserializeContext.new(targets: [default_model, default_nested_model],
387
+ access_control: access_control)
388
+ end
393
389
 
394
390
  include CanSerialize
395
391
  include CanDeserializeToNew
396
392
  include CanDeserializeToExisting
397
393
 
398
- it "can update the nested value" do
399
- new_view = default_view.merge("nested" => default_nested_view.merge("member" => "changed"))
394
+ it 'can update the nested value' do
395
+ new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
400
396
 
401
397
  vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
402
398
 
403
- assert(default_model.equal?(vm.model), "returned model was not the same")
404
- assert(default_nested_model.equal?(vm.model.nested), "returned nested model was not the same")
399
+ assert(default_model.equal?(vm.model), 'returned model was not the same')
400
+ assert(default_nested_model.equal?(vm.model.nested), 'returned nested model was not the same')
405
401
 
406
- assert_equal("changed", default_model.nested.member)
402
+ assert_equal('changed', default_model.nested.member)
407
403
 
408
404
  assert_unchanged(vm)
409
405
  assert_edited(vm.nested, changed_attributes: [:member])
410
406
  end
411
407
 
412
- it "can replace the nested value" do
408
+ it 'can replace the nested value' do
413
409
  # The value will be unified if it is different after deserialization
414
- new_view = default_view.merge("nested" => default_nested_view.merge("member" => "changed"))
410
+ new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
415
411
 
416
412
  partial_update_context = TestDeserializeContext.new(targets: [default_model],
417
413
  access_control: access_control)
418
414
 
419
415
  vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: partial_update_context)
420
416
 
421
- assert(default_model.equal?(vm.model), "returned model was not the same")
422
- refute(default_nested_model.equal?(vm.model.nested), "returned nested model was the same")
417
+ assert(default_model.equal?(vm.model), 'returned model was not the same')
418
+ refute(default_nested_model.equal?(vm.model.nested), 'returned nested model was the same')
423
419
 
424
420
  assert_edited(vm, new: false, changed_attributes: [:nested])
425
421
  assert_edited(vm.nested, new: true, changed_attributes: [:member])
426
422
  end
427
423
  end
428
424
 
429
- describe "with array of nested viewmodel" do
430
- let(:default_nested_model_1) { Nested.new("member1") }
431
- let(:default_nested_view_1) { view_base.merge("_type" => "Nested", "member" => "member1") }
425
+ describe 'with array of nested viewmodel' do
426
+ let(:default_nested_model_1) { Nested.new('member1') }
427
+ let(:default_nested_view_1) { view_base.merge('_type' => 'Nested', 'member' => 'member1') }
432
428
 
433
- let(:default_nested_model_2) { Nested.new("member2") }
434
- let(:default_nested_view_2) { view_base.merge("_type" => "Nested", "member" => "member2") }
429
+ let(:default_nested_model_2) { Nested.new('member2') }
430
+ let(:default_nested_view_2) { view_base.merge('_type' => 'Nested', 'member' => 'member2') }
435
431
 
436
- let(:attributes) {{ simple: {}, nested: { using: NestedView, array: true } }}
432
+ let(:attributes) { { simple: {}, nested: { using: NestedView, array: true } } }
437
433
 
438
434
  let(:default_view_values) { { nested: [default_nested_view_1, default_nested_view_2] } }
439
435
  let(:default_model_values) { { nested: [default_nested_model_1, default_nested_model_2] } }
@@ -447,20 +443,20 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
447
443
  include CanDeserializeToNew
448
444
  include CanDeserializeToExisting
449
445
 
450
- it "rejects change to attribute" do
451
- new_view = default_view.merge("nested" => "terrible")
446
+ it 'rejects change to attribute' do
447
+ new_view = default_view.merge('nested' => 'terrible')
452
448
  ex = assert_raises(ViewModel::DeserializationError::InvalidAttributeType) do
453
449
  viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
454
450
  end
455
- assert_equal("nested", ex.attribute)
456
- assert_equal("Array", ex.expected_type)
457
- assert_equal("String", ex.provided_type)
451
+ assert_equal('nested', ex.attribute)
452
+ assert_equal('Array', ex.expected_type)
453
+ assert_equal('String', ex.provided_type)
458
454
  end
459
455
 
460
- it "can edit a nested value" do
461
- default_view["nested"][0]["member"] = "changed"
456
+ it 'can edit a nested value' do
457
+ default_view['nested'][0]['member'] = 'changed'
462
458
  vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
463
- assert(default_model.equal?(vm.model), "returned model was not the same")
459
+ assert(default_model.equal?(vm.model), 'returned model was not the same')
464
460
  assert_equal(2, vm.model.nested.size)
465
461
  assert(default_nested_model_1.equal?(vm.model.nested[0]))
466
462
  assert(default_nested_model_2.equal?(vm.model.nested[1]))
@@ -469,18 +465,18 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
469
465
  assert_edited(vm.nested[0], changed_attributes: [:member])
470
466
  end
471
467
 
472
- it "can append a nested value" do
473
- default_view["nested"] << view_base.merge("_type" => "Nested", "member" => "member3")
468
+ it 'can append a nested value' do
469
+ default_view['nested'] << view_base.merge('_type' => 'Nested', 'member' => 'member3')
474
470
 
475
471
  vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
476
472
 
477
- assert(default_model.equal?(vm.model), "returned model was not the same")
473
+ assert(default_model.equal?(vm.model), 'returned model was not the same')
478
474
  assert_equal(3, vm.model.nested.size)
479
475
  assert(default_nested_model_1.equal?(vm.model.nested[0]))
480
476
  assert(default_nested_model_2.equal?(vm.model.nested[1]))
481
477
 
482
478
  vm.model.nested.each_with_index do |nvm, i|
483
- assert_equal("member#{i+1}", nvm.member)
479
+ assert_equal("member#{i + 1}", nvm.member)
484
480
  end
485
481
 
486
482
  assert_edited(vm, changed_attributes: [:nested])
@@ -488,5 +484,4 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
488
484
  end
489
485
  end
490
486
  end
491
-
492
487
  end