iknow_view_models 3.2.1 → 3.2.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fa0ab7a6ce71bd40dbb00eea4f73c33a1c3f442ccf349626154c6bf2974088e
4
- data.tar.gz: 298c6f0483d477bf48f849ad380c9b7bd6eb7d4a55763ba10d1639c2d2181103
3
+ metadata.gz: 89b29591362703c3bed79c996f0de85f7c8c1f65506bfd70b20f6abcf90f3375
4
+ data.tar.gz: 81af7a5b3dd3d2c6531019fd65f10d5bcb382a943088eba6e5b16a0eb45d2253
5
5
  SHA512:
6
- metadata.gz: 54c754abf844d1a4a62124df1476c3870f487b56de1108acabdb0b57acca108581817df170c318cd9d8edd0930314286d498a3d1ba9e8b68ae87a928dbfa73e9
7
- data.tar.gz: 905754efd90b6176b5f7271b1cd997df974ac35dde9afdbaa7612e4a5ec722c942b1021fb565e693efac6df30aa67205d39b6adc9ba3fa64d0db401ce99d7915
6
+ metadata.gz: 185fd079af273bbb14f617f38539b3b72f181e8bdc9af04151705267f6a4d3f21eed99d02401c4010f4d124f0d505b51f9283353bf7da0ae84fa62afbb093ad0
7
+ data.tar.gz: 3b4dec46423b5bd7090de5c4f1e712e4ce5ef71e969838a52bed724bb42bef6b43c521a32e78c2b0ec948924a6f4311f05607472a4f6061e152413d465b867de
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IknowViewModels
4
- VERSION = '3.2.1'
4
+ VERSION = '3.2.6'
5
5
  end
@@ -245,7 +245,7 @@ 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
+ Base64.urlsafe_encode64(Digest::MD5.digest(version_string), padding: false)
249
249
  end
250
250
 
251
251
  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
@@ -17,6 +17,8 @@ module ViewModel::ActiveRecord::Controller
17
17
  include ViewModel::ActiveRecord::CollectionNestedController
18
18
  include ViewModel::ActiveRecord::SingularNestedController
19
19
 
20
+ MIGRATION_VERSION_HEADER = 'X-ViewModel-Versions'
21
+
20
22
  def show(scope: nil, viewmodel_class: self.viewmodel_class, serialize_context: new_serialize_context(viewmodel_class: viewmodel_class))
21
23
  view = nil
22
24
  pre_rendered = viewmodel_class.transaction do
@@ -96,11 +98,24 @@ module ViewModel::ActiveRecord::Controller
96
98
  def migration_versions
97
99
  @migration_versions ||=
98
100
  begin
99
- versions = parse_param(
100
- :versions,
101
- default: {},
102
- with: IknowParams::Serializer::HashOf.new(
103
- IknowParams::Serializer::String, IknowParams::Serializer::Integer))
101
+ version_spec =
102
+ if params.include?(:versions)
103
+ params[:versions]
104
+ elsif request.headers.include?(MIGRATION_VERSION_HEADER)
105
+ begin
106
+ JSON.parse(request.headers[MIGRATION_VERSION_HEADER])
107
+ rescue JSON::ParserError
108
+ raise ViewModel::Error.new(status: 400, detail: "Invalid JSON in #{MIGRATION_VERSION_HEADER}")
109
+ end
110
+ else
111
+ {}
112
+ end
113
+
114
+ versions =
115
+ IknowParams::Parser.parse_value(
116
+ version_spec,
117
+ with: IknowParams::Serializer::HashOf.new(
118
+ IknowParams::Serializer::String, IknowParams::Serializer::Integer))
104
119
 
105
120
  migration_versions = {}
106
121
 
@@ -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]
@@ -7,6 +7,8 @@ require 'view_model/active_record/controller'
7
7
  require_relative '../helpers/arvm_test_utilities'
8
8
  require_relative '../helpers/arvm_test_models'
9
9
 
10
+ require 'action_controller'
11
+
10
12
  require 'acts_as_manual_list'
11
13
 
12
14
  # models for ARVM controller test
@@ -145,11 +147,11 @@ end
145
147
 
146
148
  ## Dummy Rails Controllers
147
149
  class DummyController
148
- attr_reader :params, :status
150
+ attr_reader :params, :headers, :status
149
151
 
150
- def initialize(**params)
151
- # in Rails 5, this will not be a hash, which weakens the value of the test.
152
- @params = params.with_indifferent_access
152
+ def initialize(headers: {}, params: {})
153
+ @params = ActionController::Parameters.new(params)
154
+ @headers = ActionDispatch::Http::Headers.from_hash({}).merge!(headers)
153
155
  @status = 200
154
156
  end
155
157
 
@@ -192,6 +194,11 @@ class DummyController
192
194
  JSON.parse(json_response)
193
195
  end
194
196
 
197
+ # for request.params and request.headers
198
+ def request
199
+ self
200
+ end
201
+
195
202
  class << self
196
203
  def inherited(subclass)
197
204
  subclass.initialize_rescue_blocks
@@ -98,7 +98,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
98
98
  end
99
99
 
100
100
  def test_show
101
- parentcontroller = ParentController.new(id: @parent.id)
101
+ parentcontroller = ParentController.new(params: { id: @parent.id })
102
102
  parentcontroller.invoke(:show)
103
103
 
104
104
  assert_equal({ 'data' => @parent_view.to_hash },
@@ -110,7 +110,10 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
110
110
  end
111
111
 
112
112
  def test_migrated_show
113
- parentcontroller = ParentController.new(id: @parent.id, versions: { ParentView.view_name => 1 })
113
+ parentcontroller = ParentController.new(
114
+ params: { id: @parent.id },
115
+ headers: { 'X-ViewModel-Versions' => { ParentView.view_name => 1 }.to_json })
116
+
114
117
  parentcontroller.invoke(:show)
115
118
 
116
119
  expected_view = @parent_view.to_hash
@@ -127,6 +130,18 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
127
130
  assert_all_hooks_nested_inside_parent_hook(parentcontroller.hook_trace)
128
131
  end
129
132
 
133
+ def test_invalid_migration_header
134
+ parentcontroller = ParentController.new(
135
+ params: { id: @parent.id },
136
+ headers: { 'X-ViewModel-Versions' => 'not a json' })
137
+
138
+ parentcontroller.invoke(:show)
139
+ assert_equal(400, parentcontroller.status)
140
+ assert_match(/Invalid JSON/i,
141
+ parentcontroller.hash_response['error']['detail'],
142
+ 'json error propagated')
143
+ end
144
+
130
145
  def test_index
131
146
  p2 = Parent.create(name: 'p2')
132
147
  p2_view = ParentView.new(p2)
@@ -152,7 +167,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
152
167
  { '_type' => 'Child', 'name' => 'c2' },],
153
168
  }
154
169
 
155
- parentcontroller = ParentController.new(data: data)
170
+ parentcontroller = ParentController.new(params: { data: data })
156
171
  parentcontroller.invoke(:create)
157
172
 
158
173
  assert_equal(200, parentcontroller.status)
@@ -173,7 +188,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
173
188
  'old_name' => 'p2',
174
189
  }
175
190
 
176
- parentcontroller = ParentController.new(data: data, versions: { ParentView.view_name => 1 })
191
+ parentcontroller = ParentController.new(params: { data: data, versions: { ParentView.view_name => 1 } })
177
192
  parentcontroller.invoke(:create)
178
193
 
179
194
  assert_equal(200, parentcontroller.status)
@@ -183,14 +198,14 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
183
198
  end
184
199
 
185
200
  def test_create_empty
186
- parentcontroller = ParentController.new(data: [])
201
+ parentcontroller = ParentController.new(params: { data: [] })
187
202
  parentcontroller.invoke(:create)
188
203
 
189
204
  assert_equal(400, parentcontroller.status)
190
205
  end
191
206
 
192
207
  def test_create_invalid
193
- parentcontroller = ParentController.new(data: 42)
208
+ parentcontroller = ParentController.new(params: { data: 42 })
194
209
  parentcontroller.invoke(:create)
195
210
 
196
211
  assert_equal(400, parentcontroller.status)
@@ -201,7 +216,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
201
216
  '_type' => 'Parent',
202
217
  'name' => 'new' }
203
218
 
204
- parentcontroller = ParentController.new(id: @parent.id, data: data)
219
+ parentcontroller = ParentController.new(params: { id: @parent.id, data: data })
205
220
  parentcontroller.invoke(:create)
206
221
 
207
222
  assert_equal(200, parentcontroller.status)
@@ -216,7 +231,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
216
231
  end
217
232
 
218
233
  def test_destroy
219
- parentcontroller = ParentController.new(id: @parent.id)
234
+ parentcontroller = ParentController.new(params: { id: @parent.id })
220
235
  parentcontroller.invoke(:destroy)
221
236
 
222
237
  assert_equal(200, parentcontroller.status)
@@ -230,7 +245,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
230
245
  end
231
246
 
232
247
  def test_show_missing
233
- parentcontroller = ParentController.new(id: 9999)
248
+ parentcontroller = ParentController.new(params: { id: 9999 })
234
249
  parentcontroller.invoke(:show)
235
250
 
236
251
  assert_equal(404, parentcontroller.status)
@@ -252,7 +267,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
252
267
  'children' => [{ '_type' => 'Child',
253
268
  'age' => 42 }] }
254
269
 
255
- parentcontroller = ParentController.new(data: data)
270
+ parentcontroller = ParentController.new(params: { data: data })
256
271
  parentcontroller.invoke(:create)
257
272
 
258
273
  assert_equal({ 'error' => {
@@ -275,7 +290,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
275
290
  data = { '_type' => 'Parent',
276
291
  'children' => [{ '_type' => 'Child',
277
292
  'age' => 1 }] }
278
- parentcontroller = ParentController.new(data: data)
293
+ parentcontroller = ParentController.new(params: { data: data })
279
294
  parentcontroller.invoke(:create)
280
295
 
281
296
  assert_equal(400, parentcontroller.status)
@@ -285,7 +300,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
285
300
  end
286
301
 
287
302
  def test_destroy_missing
288
- parentcontroller = ParentController.new(id: 9999)
303
+ parentcontroller = ParentController.new(params: { id: 9999 })
289
304
  parentcontroller.invoke(:destroy)
290
305
 
291
306
  assert_equal({ 'error' => {
@@ -307,7 +322,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
307
322
  def test_nested_collection_index_associated
308
323
  _distractor = Parent.create(name: 'p2', children: [Child.new(name: 'c3', position: 1)])
309
324
 
310
- childcontroller = ChildController.new(parent_id: @parent.id)
325
+ childcontroller = ChildController.new(params: { parent_id: @parent.id })
311
326
  childcontroller.invoke(:index_associated)
312
327
 
313
328
  assert_equal(200, childcontroller.status)
@@ -334,7 +349,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
334
349
 
335
350
  def test_nested_collection_append_one
336
351
  data = { '_type' => 'Child', 'name' => 'c3' }
337
- childcontroller = ChildController.new(parent_id: @parent.id, data: data)
352
+ childcontroller = ChildController.new(params: { parent_id: @parent.id, data: data })
338
353
 
339
354
  childcontroller.invoke(:append)
340
355
 
@@ -353,7 +368,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
353
368
  data = [{ '_type' => 'Child', 'name' => 'c3' },
354
369
  { '_type' => 'Child', 'name' => 'c4' },]
355
370
 
356
- childcontroller = ChildController.new(parent_id: @parent.id, data: data)
371
+ childcontroller = ChildController.new(params: { parent_id: @parent.id, data: data })
357
372
  childcontroller.invoke(:append)
358
373
 
359
374
  assert_equal(200, childcontroller.status, childcontroller.hash_response)
@@ -376,7 +391,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
376
391
  data = [{ '_type' => 'Child', 'name' => 'newc1' },
377
392
  { '_type' => 'Child', 'name' => 'newc2' },]
378
393
 
379
- childcontroller = ChildController.new(parent_id: @parent.id, data: data)
394
+ childcontroller = ChildController.new(params: { parent_id: @parent.id, data: data })
380
395
  childcontroller.invoke(:replace)
381
396
 
382
397
  assert_equal(200, childcontroller.status, childcontroller.hash_response)
@@ -391,7 +406,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
391
406
 
392
407
  def test_nested_collection_replace_bad_data
393
408
  data = [{ 'name' => 'nc' }]
394
- childcontroller = ChildController.new(parent_id: @parent.id, data: data)
409
+ childcontroller = ChildController.new(params: { parent_id: @parent.id, data: data })
395
410
 
396
411
  childcontroller.invoke(:replace)
397
412
 
@@ -402,7 +417,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
402
417
 
403
418
  def test_nested_collection_disassociate_one
404
419
  old_child = @parent.children.first
405
- childcontroller = ChildController.new(parent_id: @parent.id, id: old_child.id)
420
+ childcontroller = ChildController.new(params: { parent_id: @parent.id, id: old_child.id })
406
421
  childcontroller.invoke(:disassociate)
407
422
 
408
423
  assert_equal(200, childcontroller.status, childcontroller.hash_response)
@@ -418,7 +433,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
418
433
  def test_nested_collection_disassociate_many
419
434
  old_children = @parent.children
420
435
 
421
- childcontroller = ChildController.new(parent_id: @parent.id)
436
+ childcontroller = ChildController.new(params: { parent_id: @parent.id })
422
437
  childcontroller.invoke(:disassociate_all)
423
438
 
424
439
  assert_equal(200, childcontroller.status, childcontroller.hash_response)
@@ -434,7 +449,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
434
449
  # direct methods on nested controller
435
450
  def test_nested_collection_destroy
436
451
  old_child = @parent.children.first
437
- childcontroller = ChildController.new(id: old_child.id)
452
+ childcontroller = ChildController.new(params: { id: old_child.id })
438
453
  childcontroller.invoke(:destroy)
439
454
 
440
455
  assert_equal(200, childcontroller.status, childcontroller.hash_response)
@@ -452,7 +467,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
452
467
  '_type' => 'Child',
453
468
  'name' => 'new_name' }
454
469
 
455
- childcontroller = ChildController.new(data: data)
470
+ childcontroller = ChildController.new(params: { data: data })
456
471
  childcontroller.invoke(:create)
457
472
 
458
473
  assert_equal(200, childcontroller.status, childcontroller.hash_response)
@@ -467,7 +482,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
467
482
  def test_nested_collection_show
468
483
  old_child = @parent.children.first
469
484
 
470
- childcontroller = ChildController.new(id: old_child.id)
485
+ childcontroller = ChildController.new(params: { id: old_child.id })
471
486
  childcontroller.invoke(:show)
472
487
 
473
488
  assert_equal({ 'data' => ChildView.new(old_child).to_hash },
@@ -482,7 +497,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
482
497
  old_label = @parent.label
483
498
 
484
499
  data = { '_type' => 'Label', 'text' => 'new label' }
485
- labelcontroller = LabelController.new(parent_id: @parent.id, data: data)
500
+ labelcontroller = LabelController.new(params: { parent_id: @parent.id, data: data })
486
501
  labelcontroller.invoke(:create_associated)
487
502
 
488
503
  assert_equal(200, labelcontroller.status, labelcontroller.hash_response)
@@ -504,7 +519,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
504
519
  def test_nested_singular_show_from_parent
505
520
  old_label = @parent.label
506
521
 
507
- labelcontroller = LabelController.new(parent_id: @parent.id)
522
+ labelcontroller = LabelController.new(params: { parent_id: @parent.id })
508
523
  labelcontroller.invoke(:show_associated)
509
524
 
510
525
  assert_equal(200, labelcontroller.status, labelcontroller.hash_response)
@@ -518,7 +533,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
518
533
  def test_nested_singular_destroy_from_parent
519
534
  old_label = @parent.label
520
535
 
521
- labelcontroller = LabelController.new(parent_id: @parent.id)
536
+ labelcontroller = LabelController.new(params: { parent_id: @parent.id })
522
537
  labelcontroller.invoke(:destroy_associated)
523
538
 
524
539
  @parent.reload
@@ -536,7 +551,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
536
551
  old_label = @parent.label
537
552
 
538
553
  data = { '_type' => 'Label', 'id' => old_label.id, 'text' => 'new label' }
539
- labelcontroller = LabelController.new(parent_id: @parent.id, data: data)
554
+ labelcontroller = LabelController.new(params: { parent_id: @parent.id, data: data })
540
555
  labelcontroller.invoke(:create_associated)
541
556
 
542
557
  assert_equal(200, labelcontroller.status, labelcontroller.hash_response)
@@ -553,7 +568,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
553
568
  def test_nested_singular_show_from_id
554
569
  old_label = @parent.label
555
570
 
556
- labelcontroller = LabelController.new(id: old_label.id)
571
+ labelcontroller = LabelController.new(params: { id: old_label.id })
557
572
  labelcontroller.invoke(:show)
558
573
 
559
574
  assert_equal(200, labelcontroller.status, labelcontroller.hash_response)
@@ -567,7 +582,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
567
582
  # foreign key violation. Destroy target instead.
568
583
  old_target = @parent.target
569
584
 
570
- targetcontroller = TargetController.new(id: old_target.id)
585
+ targetcontroller = TargetController.new(params: { id: old_target.id })
571
586
  targetcontroller.invoke(:destroy)
572
587
 
573
588
  @parent.reload
@@ -583,7 +598,7 @@ class ViewModel::ActiveRecord::ControllerTest < ActiveSupport::TestCase
583
598
  old_label = @parent.label
584
599
 
585
600
  data = { '_type' => 'Label', 'id' => old_label.id, 'text' => 'new label' }
586
- labelcontroller = LabelController.new(data: data)
601
+ labelcontroller = LabelController.new(params: { data: data })
587
602
  labelcontroller.invoke(:create)
588
603
 
589
604
  assert_equal(200, labelcontroller.status, labelcontroller.hash_response)
@@ -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.1
4
+ version: 3.2.6
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-08 00:00:00.000000000 Z
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