iknow_view_models 3.2.3 → 3.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/iknow_view_models/version.rb +1 -1
- data/lib/view_model/registry.rb +13 -1
- data/test/unit/view_model/record_test.rb +102 -84
- data/test/unit/view_model/registry_test.rb +38 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a61a46fa1aa74a456ed6a3d639b5bfa5a2e246b8b3772e2a34fab2bf9013722
|
4
|
+
data.tar.gz: 9beba4e8d176ab4ae5da14e66da70f2747a8ee68faa5ba1b79821f7dd956ab56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ffc79be3e1479fe94f53400558133e0d98a333112502f183e8d78da9da95cb08187ab3eff20dd408ca12ed9172b74c25d15a6343407349b46b21576d2698d99
|
7
|
+
data.tar.gz: be2a8e88134247eed00a3adc051c741f86ac3437d6f47c921ecfd1c16d5d4d39104901aaf8cc3b29804fcd62e1c8ccfd89943d1457b89fc6b4976513e2d57069
|
data/lib/view_model/registry.rb
CHANGED
@@ -6,7 +6,8 @@ class ViewModel::Registry
|
|
6
6
|
DEFERRED_NAME = Object.new
|
7
7
|
|
8
8
|
class << self
|
9
|
-
delegate :for_view_name, :register, :default_view_name, :infer_model_class_name,
|
9
|
+
delegate :for_view_name, :register, :default_view_name, :infer_model_class_name,
|
10
|
+
:clear_removed_classes!, :all, :roots,
|
10
11
|
to: :instance
|
11
12
|
end
|
12
13
|
|
@@ -33,6 +34,17 @@ class ViewModel::Registry
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
37
|
+
def all
|
38
|
+
@lock.synchronize do
|
39
|
+
resolve_deferred_classes
|
40
|
+
@viewmodel_classes_by_name.values
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def roots
|
45
|
+
all.select { |c| c.root? }
|
46
|
+
end
|
47
|
+
|
36
48
|
def register(viewmodel, as: DEFERRED_NAME)
|
37
49
|
@lock.synchronize do
|
38
50
|
@deferred_viewmodel_classes << [viewmodel, as]
|
@@ -365,122 +365,140 @@ class ViewModel::RecordTest < ActiveSupport::TestCase
|
|
365
365
|
end
|
366
366
|
end
|
367
367
|
|
368
|
-
|
368
|
+
describe 'nesting' do
|
369
|
+
let(:nested_model_class) do
|
370
|
+
klass = Struct.new(:member)
|
371
|
+
Object.const_set(:Nested, klass)
|
372
|
+
klass
|
373
|
+
end
|
369
374
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
+
let(:nested_viewmodel_class) do
|
376
|
+
mc = nested_model_class
|
377
|
+
klass = Class.new(TestViewModel) do
|
378
|
+
self.view_name = 'Nested'
|
379
|
+
self.model_class = mc
|
380
|
+
attribute :member
|
381
|
+
end
|
382
|
+
Object.const_set(:NestedView, klass)
|
383
|
+
klass
|
384
|
+
end
|
375
385
|
|
376
|
-
|
377
|
-
|
378
|
-
|
386
|
+
def teardown
|
387
|
+
Object.send(:remove_const, :Nested)
|
388
|
+
Object.send(:remove_const, :NestedView)
|
389
|
+
ActiveSupport::Dependencies::Reference.clear!
|
390
|
+
super
|
391
|
+
end
|
379
392
|
|
380
|
-
|
393
|
+
describe 'with nested viewmodel' do
|
394
|
+
let(:default_nested_model) { nested_model_class.new('member') }
|
395
|
+
let(:default_nested_view) { view_base.merge('_type' => 'Nested', 'member' => 'member') }
|
381
396
|
|
382
|
-
|
383
|
-
let(:default_model_values) { { nested: default_nested_model } }
|
397
|
+
let(:attributes) { { simple: {}, nested: { using: nested_viewmodel_class } } }
|
384
398
|
|
385
|
-
|
386
|
-
|
387
|
-
access_control: access_control)
|
388
|
-
end
|
399
|
+
let(:default_view_values) { { nested: default_nested_view } }
|
400
|
+
let(:default_model_values) { { nested: default_nested_model } }
|
389
401
|
|
390
|
-
|
391
|
-
|
392
|
-
|
402
|
+
let(:update_context) do
|
403
|
+
TestDeserializeContext.new(targets: [default_model, default_nested_model],
|
404
|
+
access_control: access_control)
|
405
|
+
end
|
393
406
|
|
394
|
-
|
395
|
-
|
407
|
+
include CanSerialize
|
408
|
+
include CanDeserializeToNew
|
409
|
+
include CanDeserializeToExisting
|
396
410
|
|
397
|
-
|
411
|
+
it 'can update the nested value' do
|
412
|
+
new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
|
398
413
|
|
399
|
-
|
400
|
-
assert(default_nested_model.equal?(vm.model.nested), 'returned nested model was not the same')
|
414
|
+
vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
|
401
415
|
|
402
|
-
|
416
|
+
assert(default_model.equal?(vm.model), 'returned model was not the same')
|
417
|
+
assert(default_nested_model.equal?(vm.model.nested), 'returned nested model was not the same')
|
403
418
|
|
404
|
-
|
405
|
-
assert_edited(vm.nested, changed_attributes: [:member])
|
406
|
-
end
|
419
|
+
assert_equal('changed', default_model.nested.member)
|
407
420
|
|
408
|
-
|
409
|
-
|
410
|
-
|
421
|
+
assert_unchanged(vm)
|
422
|
+
assert_edited(vm.nested, changed_attributes: [:member])
|
423
|
+
end
|
411
424
|
|
412
|
-
|
413
|
-
|
425
|
+
it 'can replace the nested value' do
|
426
|
+
# The value will be unified if it is different after deserialization
|
427
|
+
new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
|
414
428
|
|
415
|
-
|
429
|
+
partial_update_context = TestDeserializeContext.new(targets: [default_model],
|
430
|
+
access_control: access_control)
|
416
431
|
|
417
|
-
|
418
|
-
refute(default_nested_model.equal?(vm.model.nested), 'returned nested model was the same')
|
432
|
+
vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: partial_update_context)
|
419
433
|
|
420
|
-
|
421
|
-
|
434
|
+
assert(default_model.equal?(vm.model), 'returned model was not the same')
|
435
|
+
refute(default_nested_model.equal?(vm.model.nested), 'returned nested model was the same')
|
436
|
+
|
437
|
+
assert_edited(vm, new: false, changed_attributes: [:nested])
|
438
|
+
assert_edited(vm.nested, new: true, changed_attributes: [:member])
|
439
|
+
end
|
422
440
|
end
|
423
|
-
end
|
424
441
|
|
425
|
-
|
426
|
-
|
427
|
-
|
442
|
+
describe 'with array of nested viewmodel' do
|
443
|
+
let(:default_nested_model_1) { nested_model_class.new('member1') }
|
444
|
+
let(:default_nested_view_1) { view_base.merge('_type' => 'Nested', 'member' => 'member1') }
|
428
445
|
|
429
|
-
|
430
|
-
|
446
|
+
let(:default_nested_model_2) { nested_model_class.new('member2') }
|
447
|
+
let(:default_nested_view_2) { view_base.merge('_type' => 'Nested', 'member' => 'member2') }
|
431
448
|
|
432
|
-
|
449
|
+
let(:attributes) { { simple: {}, nested: { using: nested_viewmodel_class, array: true } } }
|
433
450
|
|
434
|
-
|
435
|
-
|
451
|
+
let(:default_view_values) { { nested: [default_nested_view_1, default_nested_view_2] } }
|
452
|
+
let(:default_model_values) { { nested: [default_nested_model_1, default_nested_model_2] } }
|
436
453
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
454
|
+
let(:update_context) {
|
455
|
+
TestDeserializeContext.new(targets: [default_model, default_nested_model_1, default_nested_model_2],
|
456
|
+
access_control: access_control)
|
457
|
+
}
|
441
458
|
|
442
|
-
|
443
|
-
|
444
|
-
|
459
|
+
include CanSerialize
|
460
|
+
include CanDeserializeToNew
|
461
|
+
include CanDeserializeToExisting
|
445
462
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
463
|
+
it 'rejects change to attribute' do
|
464
|
+
new_view = default_view.merge('nested' => 'terrible')
|
465
|
+
ex = assert_raises(ViewModel::DeserializationError::InvalidAttributeType) do
|
466
|
+
viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
|
467
|
+
end
|
468
|
+
assert_equal('nested', ex.attribute)
|
469
|
+
assert_equal('Array', ex.expected_type)
|
470
|
+
assert_equal('String', ex.provided_type)
|
450
471
|
end
|
451
|
-
assert_equal('nested', ex.attribute)
|
452
|
-
assert_equal('Array', ex.expected_type)
|
453
|
-
assert_equal('String', ex.provided_type)
|
454
|
-
end
|
455
472
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
473
|
+
it 'can edit a nested value' do
|
474
|
+
default_view['nested'][0]['member'] = 'changed'
|
475
|
+
vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
|
476
|
+
assert(default_model.equal?(vm.model), 'returned model was not the same')
|
477
|
+
assert_equal(2, vm.model.nested.size)
|
478
|
+
assert(default_nested_model_1.equal?(vm.model.nested[0]))
|
479
|
+
assert(default_nested_model_2.equal?(vm.model.nested[1]))
|
463
480
|
|
464
|
-
|
465
|
-
|
466
|
-
|
481
|
+
assert_unchanged(vm)
|
482
|
+
assert_edited(vm.nested[0], changed_attributes: [:member])
|
483
|
+
end
|
467
484
|
|
468
|
-
|
469
|
-
|
485
|
+
it 'can append a nested value' do
|
486
|
+
default_view['nested'] << view_base.merge('_type' => 'Nested', 'member' => 'member3')
|
470
487
|
|
471
|
-
|
488
|
+
vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
|
472
489
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
490
|
+
assert(default_model.equal?(vm.model), 'returned model was not the same')
|
491
|
+
assert_equal(3, vm.model.nested.size)
|
492
|
+
assert(default_nested_model_1.equal?(vm.model.nested[0]))
|
493
|
+
assert(default_nested_model_2.equal?(vm.model.nested[1]))
|
477
494
|
|
478
|
-
|
479
|
-
|
480
|
-
|
495
|
+
vm.model.nested.each_with_index do |nvm, i|
|
496
|
+
assert_equal("member#{i + 1}", nvm.member)
|
497
|
+
end
|
481
498
|
|
482
|
-
|
483
|
-
|
499
|
+
assert_edited(vm, changed_attributes: [:nested])
|
500
|
+
assert_edited(vm.nested[2], new: true, changed_attributes: [:member])
|
501
|
+
end
|
484
502
|
end
|
485
503
|
end
|
486
504
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/unit'
|
5
|
+
require 'minitest/hooks'
|
6
|
+
|
7
|
+
require_relative '../../helpers/arvm_test_utilities'
|
8
|
+
require_relative '../../helpers/arvm_test_models'
|
9
|
+
require_relative '../../helpers/viewmodel_spec_helpers'
|
10
|
+
|
11
|
+
require 'view_model'
|
12
|
+
require 'view_model/active_record'
|
13
|
+
|
14
|
+
class ViewModel
|
15
|
+
class RegistryTest < ActiveSupport::TestCase
|
16
|
+
using ViewModel::Utils::Collections
|
17
|
+
include ARVMTestUtilities
|
18
|
+
extend Minitest::Spec::DSL
|
19
|
+
include ViewModelSpecHelpers::ParentAndBelongsToChild
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
ViewModel::Registry.clear_removed_classes!
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'registers the views' do
|
26
|
+
assert_equal(ViewModel::Registry.for_view_name(view_name), viewmodel_class)
|
27
|
+
assert_equal(ViewModel::Registry.for_view_name(child_view_name), child_viewmodel_class)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'enumerates the views' do
|
31
|
+
assert_contains_exactly([ViewModel::ErrorView, viewmodel_class, child_viewmodel_class], ViewModel::Registry.all)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'enumerates the root views' do
|
35
|
+
assert_contains_exactly([viewmodel_class], ViewModel::Registry.roots)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iknow_view_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iKnow Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -468,6 +468,7 @@ files:
|
|
468
468
|
- test/unit/view_model/controller_test.rb
|
469
469
|
- test/unit/view_model/deserialization_error/unique_violation_test.rb
|
470
470
|
- test/unit/view_model/record_test.rb
|
471
|
+
- test/unit/view_model/registry_test.rb
|
471
472
|
- test/unit/view_model/traversal_context_test.rb
|
472
473
|
- test/unit/view_model_test.rb
|
473
474
|
homepage: https://github.com/iknow/cerego_view_models
|
@@ -527,5 +528,6 @@ test_files:
|
|
527
528
|
- test/unit/view_model/controller_test.rb
|
528
529
|
- test/unit/view_model/deserialization_error/unique_violation_test.rb
|
529
530
|
- test/unit/view_model/record_test.rb
|
531
|
+
- test/unit/view_model/registry_test.rb
|
530
532
|
- test/unit/view_model/traversal_context_test.rb
|
531
533
|
- test/unit/view_model_test.rb
|