realm-auto-migration
realm-auto-migration copied to clipboard
Cannot migrate when the field type of a field is changed
I have a CatRealm with a boolean field isPet.
Class CatRealm extends RealmObject{
boolean isPet;
}
Now, I have updated the type of isPet to Long
type.
Class CatRealm extends RealmObject{
Long isPet;
}
but the AutoMigration class is not detecting the type change and app crashes due to migration exception. How can I detect the type change on AutoMigration and execute the migration perfectly?
You're right, I don't seem to handle that, just adding/removing fields and classes, and changing attributes (index, nullable, pk).
I think the reasoning was that if you change the type of the field, the only thing AutoMigration could do automatically is remove the field and re-add the field, but you'd lose the previous values of the data.
Imagine that you have a schema with boolean isPet
and you want to transform these values to 0
and 1
for whatever reason. I was trying to figure out a good way for that with AutoMigration but it just doesn't fit in there anywhere.
So I assumed the reasonable solution is to do the
schema.addField("isPet_temp", Long.class)
.transform((obj) -> { obj.setLong("isPet_temp", obj.getBoolean("isPet") ? 1 : 0) })
.removeField("isPet")
.renameField("isPet_temp", "isPet");
dance before running auto-migration.
(on the other hand, I think I also didn't consider making this kind of auto-behavior even added as optional, because I forgot about it. whoops)
To make this more easy, i created this method:
private void changeFieldDataType(DynamicRealm realm, Class<?> newDataType, String entity, final String field, final Command changeFieldDataType) {
final String tempField = TEMP_PREFIX+field;
RealmObjectSchema schema = realm.getSchema().get(entity);
if (schema != null) {
schema.addField(tempField, newDataType);
schema.transform(new RealmObjectSchema.Function() {
@Override
public void apply(@NonNull DynamicRealmObject obj) {
changeFieldDataType.execute(obj, tempField, field);
}
})
.removeField(field)
.renameField(tempField, field);
}
}
Command is an interface that help us to implement Command Pattern, this way we could create little data type conversions to pass to changeFieldDataType() , like this:
public class DoubleStringCommand implements Command {
@Override
public void execute(DynamicRealmObject object, String tempField, String field) {
object.setString(tempField, String.valueOf((object.getDouble(field))));
}
}
I think this approach could be improved a little bit to be more friendly if "AutoMigration" turns into a library and have a bunch of commands inside.