iknow_view_models 3.2.2 → 3.2.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a86b2b9fdc89ee421bcb155ae29e3ac4f2c809be4d40e483a405337f8729a7f9
4
- data.tar.gz: 8fd1c498264a0eefe30d9c3c6a35c4f005a94aaf71b03d37044a23212cb90eb4
3
+ metadata.gz: 4873d88f99bcdf0d63c3db8cbf36af0990bd9dd88bca0e170159b873b8aa7212
4
+ data.tar.gz: b190cb5ec7806dfe4f8decbf4acf8f54b7fcc0857f271d1417b4d680a87c0622
5
5
  SHA512:
6
- metadata.gz: c2a2fd321cf605709eb398771cd6cc475869e80c59d5a4934a2cf5429cfa3e1a6a5e3e74f358227793ff2cc7ce10a1eff46fe3c4db20e859d49d54be306b4afb
7
- data.tar.gz: cfb7009b02acbebce85d3ad41205549430370710633d51176ac8596acf6a83fb98f0e76132bf850baf37da36acfe402afc21d00c8996f66ca2a98f62a9380dc1
6
+ metadata.gz: 57c4fad3880aa1ce8f3434827df3dd6a789561a0f3bd8210b774c86258b8a0d4be777cbb827760f6c405b7caa61875efb8a780b3a2a9d7eff203315490d5f450
7
+ data.tar.gz: ffe26b3f24098c1ce7bd07453ce5a4f9a0bfd9611e57a53ccb7394b98fc2b8af724dc598bca85e0d2713c457d3fb5cc8575006ed947ade06aa7efd11f4436c16
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IknowViewModels
4
- VERSION = '3.2.2'
4
+ VERSION = '3.2.7'
5
5
  end
@@ -245,7 +245,9 @@ class ViewModel
245
245
 
246
246
  def schema_hash(schema_versions)
247
247
  version_string = schema_versions.to_a.sort.join(',')
248
- Base64.urlsafe_encode64(Digest::MD5.digest(version_string))
248
+ # We want a short hash value, as this will be used in cache keys
249
+ hash = Digest::SHA256.digest(version_string).byteslice(0, 16)
250
+ Base64.urlsafe_encode64(hash, padding: false)
249
251
  end
250
252
 
251
253
  def preload_for_serialization(viewmodels, serialize_context: new_serialize_context, include_referenced: true, lock: nil)
@@ -224,7 +224,7 @@ class ViewModel::ActiveRecord < ViewModel::Record
224
224
  DeepPreloader::Spec.new(association_specs)
225
225
  end
226
226
 
227
- def dependent_viewmodels(seen = Set.new, include_referenced: true)
227
+ def dependent_viewmodels(seen = Set.new, include_referenced: true, include_external: true)
228
228
  return if seen.include?(self)
229
229
 
230
230
  seen << self
@@ -232,19 +232,20 @@ class ViewModel::ActiveRecord < ViewModel::Record
232
232
  _members.each_value do |data|
233
233
  next unless data.is_a?(AssociationData)
234
234
  next unless include_referenced || !data.referenced?
235
+ next unless include_external || !data.external?
235
236
 
236
237
  data.viewmodel_classes.each do |vm|
237
- vm.dependent_viewmodels(seen, include_referenced: include_referenced)
238
+ vm.dependent_viewmodels(seen, include_referenced: include_referenced, include_external: include_external)
238
239
  end
239
240
  end
240
241
 
241
242
  seen
242
243
  end
243
244
 
244
- def deep_schema_version(include_referenced: true)
245
+ def deep_schema_version(include_referenced: true, include_external: true)
245
246
  (@deep_schema_version ||= {})[include_referenced] ||=
246
247
  begin
247
- dependent_viewmodels(include_referenced: include_referenced).each_with_object({}) do |view, h|
248
+ dependent_viewmodels(include_referenced: include_referenced, include_external: include_external).each_with_object({}) do |view, h|
248
249
  h[view.view_name] = view.schema_version
249
250
  end.freeze
250
251
  end
@@ -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, :clear_removed_classes!,
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
- Nested = Struct.new(:member)
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
- class NestedView < TestViewModel
371
- self.view_name = 'Nested'
372
- self.model_class = Nested
373
- attribute :member
374
- end
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
- 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') }
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
- let(:attributes) { { simple: {}, nested: { using: NestedView } } }
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
- let(:default_view_values) { { nested: default_nested_view } }
383
- let(:default_model_values) { { nested: default_nested_model } }
397
+ let(:attributes) { { simple: {}, nested: { using: nested_viewmodel_class } } }
384
398
 
385
- let(:update_context) do
386
- TestDeserializeContext.new(targets: [default_model, default_nested_model],
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
- include CanSerialize
391
- include CanDeserializeToNew
392
- include CanDeserializeToExisting
402
+ let(:update_context) do
403
+ TestDeserializeContext.new(targets: [default_model, default_nested_model],
404
+ access_control: access_control)
405
+ end
393
406
 
394
- it 'can update the nested value' do
395
- new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
407
+ include CanSerialize
408
+ include CanDeserializeToNew
409
+ include CanDeserializeToExisting
396
410
 
397
- vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
411
+ it 'can update the nested value' do
412
+ new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
398
413
 
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')
414
+ vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
401
415
 
402
- assert_equal('changed', default_model.nested.member)
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
- assert_unchanged(vm)
405
- assert_edited(vm.nested, changed_attributes: [:member])
406
- end
419
+ assert_equal('changed', default_model.nested.member)
407
420
 
408
- it 'can replace the nested value' do
409
- # The value will be unified if it is different after deserialization
410
- new_view = default_view.merge('nested' => default_nested_view.merge('member' => 'changed'))
421
+ assert_unchanged(vm)
422
+ assert_edited(vm.nested, changed_attributes: [:member])
423
+ end
411
424
 
412
- partial_update_context = TestDeserializeContext.new(targets: [default_model],
413
- access_control: access_control)
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
- vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: partial_update_context)
429
+ partial_update_context = TestDeserializeContext.new(targets: [default_model],
430
+ access_control: access_control)
416
431
 
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')
432
+ vm = viewmodel_class.deserialize_from_view(new_view, deserialize_context: partial_update_context)
419
433
 
420
- assert_edited(vm, new: false, changed_attributes: [:nested])
421
- assert_edited(vm.nested, new: true, changed_attributes: [:member])
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
- 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') }
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
- let(:default_nested_model_2) { Nested.new('member2') }
430
- let(:default_nested_view_2) { view_base.merge('_type' => 'Nested', 'member' => 'member2') }
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
- let(:attributes) { { simple: {}, nested: { using: NestedView, array: true } } }
449
+ let(:attributes) { { simple: {}, nested: { using: nested_viewmodel_class, array: true } } }
433
450
 
434
- let(:default_view_values) { { nested: [default_nested_view_1, default_nested_view_2] } }
435
- let(:default_model_values) { { nested: [default_nested_model_1, default_nested_model_2] } }
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
- let(:update_context) {
438
- TestDeserializeContext.new(targets: [default_model, default_nested_model_1, default_nested_model_2],
439
- access_control: access_control)
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
- include CanSerialize
443
- include CanDeserializeToNew
444
- include CanDeserializeToExisting
459
+ include CanSerialize
460
+ include CanDeserializeToNew
461
+ include CanDeserializeToExisting
445
462
 
446
- it 'rejects change to attribute' do
447
- new_view = default_view.merge('nested' => 'terrible')
448
- ex = assert_raises(ViewModel::DeserializationError::InvalidAttributeType) do
449
- viewmodel_class.deserialize_from_view(new_view, deserialize_context: update_context)
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
- it 'can edit a nested value' do
457
- default_view['nested'][0]['member'] = 'changed'
458
- vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
459
- assert(default_model.equal?(vm.model), 'returned model was not the same')
460
- assert_equal(2, vm.model.nested.size)
461
- assert(default_nested_model_1.equal?(vm.model.nested[0]))
462
- assert(default_nested_model_2.equal?(vm.model.nested[1]))
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
- assert_unchanged(vm)
465
- assert_edited(vm.nested[0], changed_attributes: [:member])
466
- end
481
+ assert_unchanged(vm)
482
+ assert_edited(vm.nested[0], changed_attributes: [:member])
483
+ end
467
484
 
468
- it 'can append a nested value' do
469
- default_view['nested'] << view_base.merge('_type' => 'Nested', 'member' => 'member3')
485
+ it 'can append a nested value' do
486
+ default_view['nested'] << view_base.merge('_type' => 'Nested', 'member' => 'member3')
470
487
 
471
- vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
488
+ vm = viewmodel_class.deserialize_from_view(default_view, deserialize_context: update_context)
472
489
 
473
- assert(default_model.equal?(vm.model), 'returned model was not the same')
474
- assert_equal(3, vm.model.nested.size)
475
- assert(default_nested_model_1.equal?(vm.model.nested[0]))
476
- assert(default_nested_model_2.equal?(vm.model.nested[1]))
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
- vm.model.nested.each_with_index do |nvm, i|
479
- assert_equal("member#{i + 1}", nvm.member)
480
- end
495
+ vm.model.nested.each_with_index do |nvm, i|
496
+ assert_equal("member#{i + 1}", nvm.member)
497
+ end
481
498
 
482
- assert_edited(vm, changed_attributes: [:nested])
483
- assert_edited(vm.nested[2], new: true, changed_attributes: [:member])
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.2
4
+ version: 3.2.7
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-15 00:00:00.000000000 Z
11
+ date: 2020-10-21 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