iknow_view_models 3.1.8 → 3.2.0
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 +4 -4
- data/.circleci/config.yml +6 -6
- data/.rubocop.yml +5 -0
- data/Appraisals +3 -3
- data/Gemfile +6 -2
- data/gemfiles/{rails_6_0_beta.gemfile → rails_6_0.gemfile} +2 -2
- data/iknow_view_models.gemspec +2 -1
- data/lib/iknow_view_models/version.rb +1 -1
- data/lib/view_model.rb +14 -3
- data/lib/view_model/active_record.rb +1 -1
- data/lib/view_model/active_record/cache.rb +110 -32
- data/lib/view_model/active_record/cache/cacheable_view.rb +2 -2
- data/lib/view_model/active_record/controller.rb +53 -1
- data/lib/view_model/migratable_view.rb +78 -0
- data/lib/view_model/migration.rb +48 -0
- data/lib/view_model/migration/no_path_error.rb +25 -0
- data/lib/view_model/migration/one_way_error.rb +23 -0
- data/lib/view_model/migration/unspecified_version_error.rb +23 -0
- data/lib/view_model/migrator.rb +108 -0
- data/lib/view_model/record.rb +4 -1
- data/lib/view_model/test_helpers/arvm_builder.rb +2 -1
- data/nix/dependencies.nix +5 -0
- data/nix/gem/generate.rb +2 -1
- data/shell.nix +8 -3
- data/test/helpers/controller_test_helpers.rb +14 -0
- data/test/helpers/viewmodel_spec_helpers.rb +67 -2
- data/test/unit/view_model/active_record/cache_test.rb +41 -5
- data/test/unit/view_model/active_record/controller_test.rb +34 -0
- data/test/unit/view_model/active_record/migration_test.rb +161 -0
- metadata +31 -9
- data/.travis.yml +0 -31
- data/appveyor.yml +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8031b0e3cf50931cfdc65ee1c530efc4210566f2951ab5d6187f80d75848ac2a
|
4
|
+
data.tar.gz: bad21c087fff5def9362bd93576e0f9f0aeb8ec8ddc4f5ff6eb6849e879168c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17edcc7ab94fa8fa3a9b34e209a3d2feebb1c31fc1d3d619c36d3d9f602312e9ff13c1e0bc0974c2df070084b8b3fa7de3a2f7c74c38a3dbd04976ee166854aa
|
7
|
+
data.tar.gz: e176a0df288c029bea2d083c03492b6a5370e78a4c35164eaadf284b66de9120dfe60eda3dc6bca5e2845b71a865f4996fd17124462d06a70156249fd709a066
|
data/.circleci/config.yml
CHANGED
@@ -102,15 +102,15 @@ workflows:
|
|
102
102
|
build:
|
103
103
|
jobs:
|
104
104
|
- test:
|
105
|
-
name: 'ruby 2.6 rails 5.2 pg
|
105
|
+
name: 'ruby 2.6 rails 5.2 pg 12'
|
106
106
|
ruby-version: "2.6"
|
107
|
-
pg-version: "
|
107
|
+
pg-version: "12"
|
108
108
|
gemfile: gemfiles/rails_5_2.gemfile
|
109
109
|
- test:
|
110
|
-
name: 'ruby 2.
|
111
|
-
ruby-version: "2.
|
112
|
-
pg-version: "
|
113
|
-
gemfile: gemfiles/
|
110
|
+
name: 'ruby 2.7 rails 6.0 pg 12'
|
111
|
+
ruby-version: "2.7"
|
112
|
+
pg-version: "12"
|
113
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
114
114
|
- publish:
|
115
115
|
filters:
|
116
116
|
branches:
|
data/.rubocop.yml
ADDED
data/Appraisals
CHANGED
@@ -3,7 +3,7 @@ appraise "rails-5-2" do
|
|
3
3
|
gem "activesupport", "~> 5.2.0"
|
4
4
|
end
|
5
5
|
|
6
|
-
appraise "rails-6-0
|
7
|
-
gem "activerecord", "~> 6.0.0
|
8
|
-
gem "activesupport", "~> 6.0.0
|
6
|
+
appraise "rails-6-0" do
|
7
|
+
gem "activerecord", "~> 6.0.0"
|
8
|
+
gem "activesupport", "~> 6.0.0"
|
9
9
|
end
|
data/Gemfile
CHANGED
@@ -3,9 +3,13 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in cerego_view_models.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
# Add our linter rules as a development dependency
|
7
|
+
gem 'rubocop'
|
8
|
+
gem 'rubocop-iknow'
|
9
|
+
|
6
10
|
# Test metadata collection for circleci
|
7
11
|
gem 'minitest-ci'
|
8
12
|
|
9
13
|
# Override gemspec for development version preferences
|
10
|
-
gem 'activerecord', '~>
|
11
|
-
gem 'activesupport', '~>
|
14
|
+
gem 'activerecord', '~> 6.0.0'
|
15
|
+
gem 'activesupport', '~> 6.0.0'
|
data/iknow_view_models.gemspec
CHANGED
@@ -36,13 +36,14 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_dependency "lazily"
|
37
37
|
spec.add_dependency "renum"
|
38
38
|
spec.add_dependency "oj"
|
39
|
+
spec.add_dependency "rgl"
|
39
40
|
|
40
41
|
spec.add_development_dependency "appraisal"
|
41
42
|
spec.add_development_dependency "bundler"
|
42
43
|
spec.add_development_dependency "byebug"
|
43
44
|
spec.add_development_dependency "method_source"
|
44
45
|
spec.add_development_dependency "minitest-hooks"
|
45
|
-
spec.add_development_dependency "pg"
|
46
|
+
spec.add_development_dependency "pg"
|
46
47
|
spec.add_development_dependency "pry"
|
47
48
|
spec.add_development_dependency "rake"
|
48
49
|
spec.add_development_dependency "rspec-expectations"
|
data/lib/view_model.rb
CHANGED
@@ -12,7 +12,12 @@ class ViewModel
|
|
12
12
|
VERSION_ATTRIBUTE = "_version"
|
13
13
|
NEW_ATTRIBUTE = "_new"
|
14
14
|
|
15
|
-
|
15
|
+
# Migrations leave a metadata attribute _migrated on any views that they
|
16
|
+
# alter. This attribute is accessible as metadata when deserializing migrated
|
17
|
+
# input, and is included in the output serialization sent to clients.
|
18
|
+
MIGRATED_ATTRIBUTE = "_migrated"
|
19
|
+
|
20
|
+
Metadata = Struct.new(:id, :view_name, :schema_version, :new, :migrated) do
|
16
21
|
alias :new? :new
|
17
22
|
end
|
18
23
|
|
@@ -99,8 +104,9 @@ class ViewModel
|
|
99
104
|
type_name = hash.delete(ViewModel::TYPE_ATTRIBUTE)
|
100
105
|
schema_version = hash.delete(ViewModel::VERSION_ATTRIBUTE)
|
101
106
|
new = hash.delete(ViewModel::NEW_ATTRIBUTE) { false }
|
107
|
+
migrated = hash.delete(ViewModel::MIGRATED_ATTRIBUTE) { false }
|
102
108
|
|
103
|
-
Metadata.new(id, type_name, schema_version, new)
|
109
|
+
Metadata.new(id, type_name, schema_version, new, migrated)
|
104
110
|
end
|
105
111
|
|
106
112
|
def extract_reference_only_metadata(hash)
|
@@ -108,7 +114,7 @@ class ViewModel
|
|
108
114
|
id = hash.delete(ViewModel::ID_ATTRIBUTE)
|
109
115
|
type_name = hash.delete(ViewModel::TYPE_ATTRIBUTE)
|
110
116
|
|
111
|
-
Metadata.new(id, type_name, nil, false)
|
117
|
+
Metadata.new(id, type_name, nil, false, false)
|
112
118
|
end
|
113
119
|
|
114
120
|
def extract_reference_metadata(hash)
|
@@ -234,6 +240,11 @@ class ViewModel
|
|
234
240
|
schema_version == self.schema_version
|
235
241
|
end
|
236
242
|
|
243
|
+
def schema_hash(schema_versions)
|
244
|
+
version_string = schema_versions.to_a.sort.join(',')
|
245
|
+
Base64.urlsafe_encode64(Digest::MD5.digest(version_string))
|
246
|
+
end
|
247
|
+
|
237
248
|
def preload_for_serialization(viewmodels, serialize_context: new_serialize_context, include_referenced: true, lock: nil)
|
238
249
|
Array.wrap(viewmodels).group_by(&:class).each do |type, views|
|
239
250
|
DeepPreloader.preload(views.map(&:model),
|
@@ -5,6 +5,7 @@ require 'iknow_cache'
|
|
5
5
|
# Cache for ViewModels that wrap ActiveRecord models.
|
6
6
|
class ViewModel::ActiveRecord::Cache
|
7
7
|
require 'view_model/active_record/cache/cacheable_view'
|
8
|
+
require 'view_model/migrator'
|
8
9
|
|
9
10
|
class UncacheableViewModelError < RuntimeError; end
|
10
11
|
|
@@ -13,13 +14,20 @@ class ViewModel::ActiveRecord::Cache
|
|
13
14
|
# If cache_group: is specified, it must be a group of a single key: `:id`
|
14
15
|
def initialize(viewmodel_class, cache_group: nil)
|
15
16
|
@viewmodel_class = viewmodel_class
|
16
|
-
|
17
|
+
|
18
|
+
@cache_group = cache_group || create_default_cache_group
|
19
|
+
@migrated_cache_group = @cache_group.register_child_group(:migrated, :version)
|
20
|
+
|
21
|
+
# /viewname/:id/viewname-currentversion
|
17
22
|
@cache = @cache_group.register_cache(cache_name)
|
23
|
+
|
24
|
+
# /viewname/:id/migrated/:oldversion/viewname-currentversion
|
25
|
+
@migrated_cache = @migrated_cache_group.register_cache(cache_name)
|
18
26
|
end
|
19
27
|
|
20
28
|
def delete(*ids)
|
21
29
|
ids.each do |id|
|
22
|
-
@cache_group.delete_all(
|
30
|
+
@cache_group.delete_all(@cache.key.new(id))
|
23
31
|
end
|
24
32
|
end
|
25
33
|
|
@@ -27,14 +35,14 @@ class ViewModel::ActiveRecord::Cache
|
|
27
35
|
@cache_group.invalidate_cache_group
|
28
36
|
end
|
29
37
|
|
30
|
-
def fetch_by_viewmodel(viewmodels, locked: false, serialize_context: @viewmodel_class.new_serialize_context)
|
38
|
+
def fetch_by_viewmodel(viewmodels, migration_versions: {}, locked: false, serialize_context: @viewmodel_class.new_serialize_context)
|
31
39
|
ids = viewmodels.map(&:id)
|
32
|
-
fetch(ids, initial_viewmodels: viewmodels, locked:
|
40
|
+
fetch(ids, initial_viewmodels: viewmodels, migration_versions: migration_versions, locked: locked, serialize_context: serialize_context)
|
33
41
|
end
|
34
42
|
|
35
|
-
def fetch(ids, initial_viewmodels: nil, locked: false, serialize_context: @viewmodel_class.new_serialize_context)
|
43
|
+
def fetch(ids, initial_viewmodels: nil, migration_versions: {}, locked: false, serialize_context: @viewmodel_class.new_serialize_context)
|
36
44
|
data_serializations = Array.new(ids.size)
|
37
|
-
worker = CacheWorker.new(serialize_context: serialize_context)
|
45
|
+
worker = CacheWorker.new(migration_versions: migration_versions, serialize_context: serialize_context)
|
38
46
|
|
39
47
|
# If initial root viewmodels were provided, visit them to ensure that they
|
40
48
|
# are visible. Other than this, no traversal callbacks are performed, as a
|
@@ -98,12 +106,14 @@ class ViewModel::ActiveRecord::Cache
|
|
98
106
|
SENTINEL = Object.new
|
99
107
|
WorklistEntry = Struct.new(:ref_name, :viewmodel)
|
100
108
|
|
101
|
-
attr_reader :serialize_context, :resolved_references
|
109
|
+
attr_reader :migration_versions, :serialize_context, :resolved_references
|
102
110
|
|
103
|
-
def initialize(serialize_context:)
|
104
|
-
@worklist
|
105
|
-
@resolved_references
|
106
|
-
@
|
111
|
+
def initialize(migration_versions:, serialize_context:)
|
112
|
+
@worklist = {}
|
113
|
+
@resolved_references = {}
|
114
|
+
@migration_versions = migration_versions
|
115
|
+
@migrated_cache_versions = {}
|
116
|
+
@serialize_context = serialize_context
|
107
117
|
end
|
108
118
|
|
109
119
|
def resolve_references!
|
@@ -141,11 +151,15 @@ class ViewModel::ActiveRecord::Cache
|
|
141
151
|
end
|
142
152
|
end
|
143
153
|
|
154
|
+
def migrated_cache_version(viewmodel_cache)
|
155
|
+
@migrated_cache_versions[viewmodel_cache] ||= viewmodel_cache.migrated_cache_version(migration_versions)
|
156
|
+
end
|
157
|
+
|
144
158
|
# Loads the specified entities from the cache and returns a hash of
|
145
159
|
# {id=>serialized_view}. Any references encountered are added to the
|
146
160
|
# worklist.
|
147
161
|
def load_from_cache(viewmodel_cache, ids)
|
148
|
-
cached_serializations = viewmodel_cache.load(ids, serialize_context: serialize_context)
|
162
|
+
cached_serializations = viewmodel_cache.load(ids, migrated_cache_version(viewmodel_cache), serialize_context: serialize_context)
|
149
163
|
|
150
164
|
cached_serializations.each_with_object({}) do |(id, cached_serialization), result|
|
151
165
|
add_refs_to_worklist(cached_serialization[:ref_cache])
|
@@ -159,17 +173,54 @@ class ViewModel::ActiveRecord::Cache
|
|
159
173
|
# added to the worklist.
|
160
174
|
def serialize_and_cache(viewmodels)
|
161
175
|
viewmodels.each_with_object({}) do |viewmodel, result|
|
162
|
-
|
176
|
+
builder = Jbuilder.new do |json|
|
163
177
|
ViewModel.serialize(viewmodel, json, serialize_context: serialize_context)
|
164
178
|
end
|
165
179
|
|
166
180
|
referenced_viewmodels = serialize_context.extract_referenced_views!
|
181
|
+
|
182
|
+
if migration_versions.present?
|
183
|
+
migrator = ViewModel::DownMigrator.new(migration_versions)
|
184
|
+
|
185
|
+
# This migration isn't given the chance to inspect/alter the contents
|
186
|
+
# of referenced views, only their presence: it's strictly less
|
187
|
+
# powerful than migrations on a fully serialized tree, as the only
|
188
|
+
# possible action on a referenced child is to delete it. The effect of
|
189
|
+
# this is that for sufficiently complex migrations where a parent view
|
190
|
+
# must introduce children or alter the contents of its referenced
|
191
|
+
# children, we may have to avoid caching while the migration is in
|
192
|
+
# use.
|
193
|
+
dummy_references = referenced_viewmodels.transform_values do |ref_vm|
|
194
|
+
{
|
195
|
+
ViewModel::TYPE_ATTRIBUTE => ref_vm.class.view_name,
|
196
|
+
ViewModel::VERSION_ATTRIBUTE => ref_vm.class.schema_version,
|
197
|
+
ViewModel::ID_ATTRIBUTE => ref_vm.id,
|
198
|
+
}.freeze
|
199
|
+
end
|
200
|
+
|
201
|
+
migrator.migrate!(builder.attributes!, references: dummy_references)
|
202
|
+
|
203
|
+
# Removed dummy references can be removed from referenced_viewmodels.
|
204
|
+
referenced_viewmodels.keep_if { |k, _| dummy_references.has_key?(k) }
|
205
|
+
|
206
|
+
# Introduced dummy references cannot be handled.
|
207
|
+
if dummy_references.keys != referenced_viewmodels.keys
|
208
|
+
version = migration_versions[viewmodel.class]
|
209
|
+
raise ViewModel::Error.new(
|
210
|
+
status: 500,
|
211
|
+
detail: "Down-migration for cacheable view #{viewmodel.class} to v#{version} must not introduce new shared references")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
data_serialization = builder.target!
|
216
|
+
|
167
217
|
add_viewmodels_to_worklist(referenced_viewmodels)
|
168
218
|
|
169
219
|
if viewmodel.class < CacheableView
|
170
220
|
cacheable_references = referenced_viewmodels.transform_values { |vm| cacheable_reference(vm) }
|
171
|
-
viewmodel.class.viewmodel_cache
|
172
|
-
|
221
|
+
target_cache = viewmodel.class.viewmodel_cache
|
222
|
+
target_cache.store(viewmodel.id, migrated_cache_version(target_cache), data_serialization, cacheable_references,
|
223
|
+
serialize_context: serialize_context)
|
173
224
|
end
|
174
225
|
|
175
226
|
result[viewmodel.id] = data_serialization
|
@@ -225,8 +276,20 @@ class ViewModel::ActiveRecord::Cache
|
|
225
276
|
end
|
226
277
|
end
|
227
278
|
|
228
|
-
def
|
229
|
-
|
279
|
+
def cache_for(migration_version)
|
280
|
+
if migration_version
|
281
|
+
@migrated_cache
|
282
|
+
else
|
283
|
+
@cache
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def key_for(id, migration_version)
|
288
|
+
if migration_version
|
289
|
+
@migrated_cache.key.new(id, migration_version)
|
290
|
+
else
|
291
|
+
@cache.key.new(id)
|
292
|
+
end
|
230
293
|
end
|
231
294
|
|
232
295
|
def id_for(key)
|
@@ -234,32 +297,47 @@ class ViewModel::ActiveRecord::Cache
|
|
234
297
|
end
|
235
298
|
|
236
299
|
# Save the provided serialization and reference data in the cache
|
237
|
-
def store(id, data_serialization, ref_cache, serialize_context:)
|
238
|
-
|
300
|
+
def store(id, migration_version, data_serialization, ref_cache, serialize_context:)
|
301
|
+
key = key_for(id, migration_version)
|
302
|
+
cache_for(migration_version).write(key, { data: data_serialization, ref_cache: ref_cache })
|
239
303
|
end
|
240
304
|
|
241
|
-
def load(ids, serialize_context:)
|
242
|
-
keys = ids.map { |id| key_for(id) }
|
243
|
-
results =
|
305
|
+
def load(ids, migration_version, serialize_context:)
|
306
|
+
keys = ids.map { |id| key_for(id, migration_version) }
|
307
|
+
results = cache_for(migration_version).read_multi(keys)
|
244
308
|
results.transform_keys! { |key| id_for(key) }
|
245
309
|
end
|
246
310
|
|
247
|
-
|
311
|
+
def cache_version
|
312
|
+
@cache_version ||=
|
313
|
+
begin
|
314
|
+
versions = @viewmodel_class.deep_schema_version(include_referenced: false)
|
315
|
+
ViewModel.schema_hash(versions)
|
316
|
+
end
|
317
|
+
end
|
248
318
|
|
249
|
-
|
319
|
+
def migrated_cache_version(migration_versions)
|
320
|
+
versions = ViewModel::Migrator.migrated_deep_schema_version(viewmodel_class, migration_versions, include_referenced: false)
|
321
|
+
version_hash = ViewModel.schema_hash(versions)
|
322
|
+
|
323
|
+
if version_hash == cache_version
|
324
|
+
# no migrations affect this view
|
325
|
+
nil
|
326
|
+
else
|
327
|
+
version_hash
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
private
|
250
332
|
|
251
333
|
def create_default_cache_group
|
252
334
|
IknowCache.register_group(@viewmodel_class.name, :id)
|
253
335
|
end
|
254
336
|
|
255
|
-
# Statically version the
|
256
|
-
# the constituent viewmodels, so that viewmodel changes force
|
337
|
+
# Statically version the cache name based on the (current) deep schema
|
338
|
+
# versions of the constituent viewmodels, so that viewmodel changes force
|
339
|
+
# invalidation.
|
257
340
|
def cache_name
|
258
|
-
"#{
|
259
|
-
end
|
260
|
-
|
261
|
-
def cache_version
|
262
|
-
version_string = @viewmodel_class.deep_schema_version(include_referenced: false).to_a.sort.join(',')
|
263
|
-
Base64.urlsafe_encode64(Digest::MD5.digest(version_string))
|
341
|
+
"vmcache_#{cache_version}"
|
264
342
|
end
|
265
343
|
end
|
@@ -40,10 +40,10 @@ module ViewModel::ActiveRecord::Cache::CacheableView
|
|
40
40
|
@viewmodel_cache
|
41
41
|
end
|
42
42
|
|
43
|
-
def serialize_from_cache(views, serialize_context:)
|
43
|
+
def serialize_from_cache(views, migration_versions: {}, locked: false, serialize_context:)
|
44
44
|
plural = views.is_a?(Array)
|
45
45
|
views = Array.wrap(views)
|
46
|
-
json_views, json_refs = viewmodel_cache.fetch_by_viewmodel(views, serialize_context: serialize_context)
|
46
|
+
json_views, json_refs = viewmodel_cache.fetch_by_viewmodel(views, locked: locked, migration_versions: migration_versions, serialize_context: serialize_context)
|
47
47
|
json_views = json_views.first unless plural
|
48
48
|
return json_views, json_refs
|
49
49
|
end
|
@@ -62,7 +62,29 @@ module ViewModel::ActiveRecord::Controller
|
|
62
62
|
end
|
63
63
|
|
64
64
|
included do
|
65
|
-
etag {
|
65
|
+
etag { migrated_deep_schema_version }
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_viewmodel_updates
|
69
|
+
super.tap do |update_hash, refs|
|
70
|
+
if migration_versions.present?
|
71
|
+
migrator = ViewModel::UpMigrator.new(migration_versions)
|
72
|
+
migrator.migrate!([update_hash, refs], references: refs)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def prerender_viewmodel(*)
|
78
|
+
super do |jbuilder|
|
79
|
+
yield(jbuilder) if block_given?
|
80
|
+
|
81
|
+
# migrate the resulting structure before it's serialized to a json string
|
82
|
+
if migration_versions.present?
|
83
|
+
tree = jbuilder.attributes!
|
84
|
+
migrator = ViewModel::DownMigrator.new(migration_versions)
|
85
|
+
migrator.migrate!(tree, references: tree['references'])
|
86
|
+
end
|
87
|
+
end
|
66
88
|
end
|
67
89
|
|
68
90
|
private
|
@@ -70,4 +92,34 @@ module ViewModel::ActiveRecord::Controller
|
|
70
92
|
def viewmodel_id
|
71
93
|
parse_param(:id)
|
72
94
|
end
|
95
|
+
|
96
|
+
def migration_versions
|
97
|
+
@migration_versions ||=
|
98
|
+
begin
|
99
|
+
versions = parse_param(
|
100
|
+
:versions,
|
101
|
+
default: {},
|
102
|
+
with: IknowParams::Serializer::HashOf.new(
|
103
|
+
IknowParams::Serializer::String, IknowParams::Serializer::Integer))
|
104
|
+
|
105
|
+
migration_versions = {}
|
106
|
+
|
107
|
+
versions.each do |view_name, required_version|
|
108
|
+
viewmodel_class = ViewModel::Registry.for_view_name(view_name)
|
109
|
+
|
110
|
+
if viewmodel_class.schema_version != required_version
|
111
|
+
migration_versions[viewmodel_class] = required_version
|
112
|
+
end
|
113
|
+
rescue ViewModel::DeserializationError::UnknownView
|
114
|
+
# Ignore requests to migrate types that no longer exist
|
115
|
+
next
|
116
|
+
end
|
117
|
+
|
118
|
+
migration_versions.freeze
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def migrated_deep_schema_version
|
123
|
+
ViewModel::Migrator.migrated_deep_schema_version(viewmodel_class, migration_versions, include_referenced: true)
|
124
|
+
end
|
73
125
|
end
|