iknow_view_models 3.2.1 → 3.2.6

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: 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