Do I need to perform a migration block when updating @PersistableEnum?

54 views Asked by At

I have a realm model setup like this:

enum RealmEnumExample: String, Codable, PersistableEnum {
    case hot, cold, cloudy, rainy
}

final class RealmExample: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var id: Int
    @Persisted var weather: RealmEnumExample
    
    init(id: Int, weather: RealmEnumExample) {
        
        super.init()
        self.id = id
        self.weather = weather
    }
    
    override init() {
        super.init()
    }
}

If I remove cold and cloudy from RealmNumExample and add warm do I need to perform a realm migration block in addition to updating the schema version? Realm documentation says that when adding and removing properties realm automatically does the migration for you but it is not clear with PersistableEnums in cases like these. When would renaming a property be relevant in this example? Lets say I "renamed" cloudy to warm wouldn't that be the same as removing cloudy and adding warm, therefore, not needing a migration block in that case as well and only needing to update the schema version?

I am confused on when it would be appropriate to resort to "renaming" properties in this scenario and doing a migration block or allowing realm to do the migration if it is handling it as adding and removing properties.

1

There are 1 answers

2
Jay On BEST ANSWER

The answer is yes, if the Realm PersistableEnum is changed in a destructive way, a migration will need to be performed to align the existing object properties with the removed Enum cases.

  • Adding a .warm case only would be a non-destructive change and since no objects have .warm yet, there's nothing to migrate.

The reason is the RealmExample objects which have Enum values of cold and cloudy have the actual string value of cold and cloudy stored in the weather property (a string).

If those are removed from the Enum, the property values can no longer be mapped back the Enum to be resolved. e.g. cold no longer has meaning.

Updating the the version number along with a migration would be the solution. This code will map the objects that have a .cold case to the newly added .warm case.

You would insert any additional logic at that statement to determine which properties get mapped to the newly added warm case.

let vers = UInt64(4)
let config = Realm.Configuration( fileURL: pathToThisRealmFile, schemaVersion: vers, migrationBlock: { migration, oldSchemaVersion in
     print("oldSchemaVersion: \(oldSchemaVersion)")
     if (oldSchemaVersion < vers) {
        print("  performing migration")
         migration.enumerateObjects(ofType: RealmExample.className(), { oldObject, newObject in
             if oldObject!["weather"] as? String == "cold" {
                 newObject!["weather"] = RealmEnumExample.warm
             }
         })
     }
 })