iknow_view_models 3.1.5 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +6 -6
  3. data/.rubocop.yml +18 -0
  4. data/Appraisals +6 -6
  5. data/Gemfile +6 -2
  6. data/Rakefile +5 -5
  7. data/gemfiles/rails_5_2.gemfile +5 -5
  8. data/gemfiles/rails_6_0.gemfile +9 -0
  9. data/iknow_view_models.gemspec +40 -38
  10. data/lib/iknow_view_models.rb +9 -7
  11. data/lib/iknow_view_models/version.rb +1 -1
  12. data/lib/view_model.rb +31 -17
  13. data/lib/view_model/access_control.rb +5 -2
  14. data/lib/view_model/access_control/composed.rb +10 -9
  15. data/lib/view_model/access_control/open.rb +2 -0
  16. data/lib/view_model/access_control/read_only.rb +2 -0
  17. data/lib/view_model/access_control/tree.rb +11 -6
  18. data/lib/view_model/access_control_error.rb +4 -1
  19. data/lib/view_model/active_record.rb +13 -12
  20. data/lib/view_model/active_record/association_data.rb +3 -2
  21. data/lib/view_model/active_record/association_manipulation.rb +6 -4
  22. data/lib/view_model/active_record/cache.rb +114 -34
  23. data/lib/view_model/active_record/cache/cacheable_view.rb +2 -2
  24. data/lib/view_model/active_record/collection_nested_controller.rb +3 -3
  25. data/lib/view_model/active_record/controller.rb +53 -1
  26. data/lib/view_model/active_record/controller_base.rb +4 -1
  27. data/lib/view_model/active_record/nested_controller_base.rb +1 -0
  28. data/lib/view_model/active_record/update_context.rb +8 -6
  29. data/lib/view_model/active_record/update_data.rb +32 -30
  30. data/lib/view_model/active_record/update_operation.rb +17 -13
  31. data/lib/view_model/active_record/visitor.rb +0 -1
  32. data/lib/view_model/after_transaction_runner.rb +2 -2
  33. data/lib/view_model/callbacks.rb +3 -1
  34. data/lib/view_model/controller.rb +13 -3
  35. data/lib/view_model/deserialization_error.rb +15 -12
  36. data/lib/view_model/error.rb +12 -10
  37. data/lib/view_model/error_view.rb +3 -1
  38. data/lib/view_model/migratable_view.rb +78 -0
  39. data/lib/view_model/migration.rb +48 -0
  40. data/lib/view_model/migration/no_path_error.rb +26 -0
  41. data/lib/view_model/migration/one_way_error.rb +24 -0
  42. data/lib/view_model/migration/unspecified_version_error.rb +24 -0
  43. data/lib/view_model/migrator.rb +108 -0
  44. data/lib/view_model/record.rb +15 -14
  45. data/lib/view_model/reference.rb +3 -1
  46. data/lib/view_model/references.rb +8 -5
  47. data/lib/view_model/registry.rb +1 -1
  48. data/lib/view_model/schemas.rb +9 -4
  49. data/lib/view_model/serialization_error.rb +4 -1
  50. data/lib/view_model/serialize_context.rb +4 -4
  51. data/lib/view_model/test_helpers.rb +8 -3
  52. data/lib/view_model/test_helpers/arvm_builder.rb +21 -15
  53. data/lib/view_model/traversal_context.rb +8 -5
  54. data/nix/dependencies.nix +5 -0
  55. data/nix/gem/generate.rb +2 -1
  56. data/shell.nix +8 -3
  57. data/test/.rubocop.yml +14 -0
  58. data/test/helpers/arvm_test_models.rb +12 -9
  59. data/test/helpers/arvm_test_utilities.rb +5 -3
  60. data/test/helpers/controller_test_helpers.rb +44 -28
  61. data/test/helpers/match_enumerator.rb +1 -0
  62. data/test/helpers/query_logging.rb +2 -1
  63. data/test/helpers/test_access_control.rb +5 -3
  64. data/test/helpers/viewmodel_spec_helpers.rb +88 -22
  65. data/test/unit/view_model/access_control_test.rb +144 -144
  66. data/test/unit/view_model/active_record/alias_test.rb +15 -13
  67. data/test/unit/view_model/active_record/belongs_to_test.rb +40 -39
  68. data/test/unit/view_model/active_record/cache_test.rb +68 -31
  69. data/test/unit/view_model/active_record/cloner_test.rb +67 -63
  70. data/test/unit/view_model/active_record/controller_test.rb +71 -38
  71. data/test/unit/view_model/active_record/counter_test.rb +10 -9
  72. data/test/unit/view_model/active_record/customization_test.rb +59 -58
  73. data/test/unit/view_model/active_record/has_many_test.rb +112 -111
  74. data/test/unit/view_model/active_record/has_many_through_poly_test.rb +15 -14
  75. data/test/unit/view_model/active_record/has_many_through_test.rb +33 -38
  76. data/test/unit/view_model/active_record/has_one_test.rb +37 -36
  77. data/test/unit/view_model/active_record/migration_test.rb +161 -0
  78. data/test/unit/view_model/active_record/namespacing_test.rb +19 -17
  79. data/test/unit/view_model/active_record/poly_test.rb +44 -45
  80. data/test/unit/view_model/active_record/shared_test.rb +30 -28
  81. data/test/unit/view_model/active_record/version_test.rb +9 -7
  82. data/test/unit/view_model/active_record_test.rb +72 -72
  83. data/test/unit/view_model/callbacks_test.rb +19 -15
  84. data/test/unit/view_model/controller_test.rb +4 -2
  85. data/test/unit/view_model/record_test.rb +92 -97
  86. data/test/unit/view_model/traversal_context_test.rb +4 -5
  87. data/test/unit/view_model_test.rb +18 -16
  88. metadata +36 -12
  89. data/.travis.yml +0 -31
  90. data/appveyor.yml +0 -22
  91. data/gemfiles/rails_6_0_beta.gemfile +0 -9
@@ -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