Merge pull request #1290 from realm/ap/delete_model

Add Realm.deleteModel API (#573)
This commit is contained in:
Ashwin Phatak 2017-09-12 14:54:20 +05:30 committed by GitHub
commit 95ea9bd38a
6 changed files with 192 additions and 1 deletions

View File

@ -8,6 +8,7 @@ X.Y.Z Release notes
* Added Progress API `realm.syncSession.addProgressNotification` and `realm.syncSession.removeProgressNotification` * Added Progress API `realm.syncSession.addProgressNotification` and `realm.syncSession.removeProgressNotification`
* Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications * Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications
* Added `Realm.deleteFile` for deleting a Realm (#363). * Added `Realm.deleteFile` for deleting a Realm (#363).
* Added `Realm.deleteModel` for deleting a Realm model in a migration (#573).
### Bug fixes ### Bug fixes
* Adding missing TypeScript declation (#1283). * Adding missing TypeScript declation (#1283).

View File

@ -132,6 +132,12 @@ class Realm {
*/ */
delete(object) {} delete(object) {}
/**
* Deletes a Realm model, including all of its objects.
* @param {string} name - the model name
*/
deleteModel(name) {}
/** /**
* **WARNING:** This will delete **all** objects in the Realm! * **WARNING:** This will delete **all** objects in the Realm!
*/ */

View File

@ -131,6 +131,7 @@ util.createMethods(Realm.prototype, objectTypes.REALM, [
// Mutating methods: // Mutating methods:
util.createMethods(Realm.prototype, objectTypes.REALM, [ util.createMethods(Realm.prototype, objectTypes.REALM, [
'delete', 'delete',
'deleteModel',
'deleteAll', 'deleteAll',
'write', 'write',
'compact', 'compact',

5
lib/index.d.ts vendored
View File

@ -484,6 +484,11 @@ declare class Realm {
*/ */
delete(object: Realm.Object | Realm.Object[] | Realm.List<any> | Realm.Results<any> | any): void; delete(object: Realm.Object | Realm.Object[] | Realm.List<any> | Realm.Results<any> | any): void;
/**
* @returns void
*/
deleteModel(name: string): void;
/** /**
* @returns void * @returns void
*/ */

View File

@ -180,7 +180,7 @@ public:
static void remove_all_listeners(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void remove_all_listeners(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void close(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void close(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void compact(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void compact(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void delete_model(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
// properties // properties
static void get_empty(ContextType, ObjectType, ReturnValue &); static void get_empty(ContextType, ObjectType, ReturnValue &);
@ -235,6 +235,7 @@ public:
{"removeAllListeners", wrap<remove_all_listeners>}, {"removeAllListeners", wrap<remove_all_listeners>},
{"close", wrap<close>}, {"close", wrap<close>},
{"compact", wrap<compact>}, {"compact", wrap<compact>},
{"deleteModel", wrap<delete_model>},
}; };
PropertyMap<T> const properties = { PropertyMap<T> const properties = {
@ -559,6 +560,17 @@ void RealmClass<T>::delete_file(ContextType ctx, FunctionType, ObjectType this_o
} }
template<typename T>
void RealmClass<T>::delete_model(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
ValueType value = arguments[0];
SharedRealm& realm = *get_internal<T, RealmClass<T>>(this_object);
std::string model_name = Value::validated_to_string(ctx, value, "deleteModel");
ObjectStore::delete_data_for_object(realm->read_group(), model_name);
}
template<typename T> template<typename T>
void RealmClass<T>::get_default_path(ContextType ctx, ObjectType object, ReturnValue &return_value) { void RealmClass<T>::get_default_path(ContextType ctx, ObjectType object, ReturnValue &return_value) {
return_value.set(realm::js::default_path()); return_value.set(realm::js::default_path());

View File

@ -158,4 +158,170 @@ module.exports = {
} }
}); });
}, },
testDeleteModelMigration: function() {
const schema = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
}
}];
var realm = new Realm({schema: schema});
realm.write(function() {
realm.create('TestObject', ['stringValue', 1]);
});
realm.close();
realm = new Realm({schema: [], schemaVersion: 1});
TestCase.assertEqual(realm.schema.length, 0); // no models
realm.close(); // this won't delete the model
realm = new Realm({schema: schema, schemaVersion: 2});
TestCase.assertEqual(realm.objects('TestObject').length, 1); // the model objects are still there
realm.close();
// now delete the model explicitly, which should delete the objects too
realm = new Realm({schema: [], schemaVersion: 3, migration: function(oldRealm, newRealm) {
newRealm.deleteModel('TestObject');
}});
TestCase.assertEqual(realm.schema.length, 0); // no models
realm.close();
realm = new Realm({schema: schema, schemaVersion: 4});
TestCase.assertEqual(realm.objects('TestObject').length, 0);
realm.close();
},
testDeleteModelInSchema: function() {
const schema = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
}
}];
var realm = new Realm({schema: schema});
realm.write(function() {
realm.create('TestObject', ['stringValue', 1]);
});
realm.close();
// now delete the model explicitly, but it should remain as it's still in the schema
// only the rows should get deleted
realm = new Realm({schema: schema, schemaVersion: 1, migration: function(oldRealm, newRealm) {
newRealm.deleteModel('TestObject');
}});
TestCase.assertEqual(realm.schema.length, 1); // model should remain
TestCase.assertEqual(realm.objects('TestObject').length, 0); // objects should be gone
realm.close();
realm = new Realm({schema: schema, schemaVersion: 2});
TestCase.assertEqual(realm.objects('TestObject').length, 0);
realm.close();
},
testDeleteModelIgnoreNotExisting: function() {
const schema = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
}
}];
var realm = new Realm({schema: schema});
realm.write(function() {
realm.create('TestObject', ['stringValue', 1]);
});
realm.close();
// non-existing models should be ignore on delete
realm = new Realm({schema: schema, schemaVersion: 1, migration: function(oldRealm, newRealm) {
newRealm.deleteModel('NonExistingModel');
}});
realm.close();
realm = new Realm({schema: schema, schemaVersion: 2});
TestCase.assertEqual(realm.objects('TestObject').length, 1);
realm.close();
},
testDeleteModelWithRelationship: function() {
const ShipSchema = {
name: 'Ship',
properties: {
ship_name: 'string',
captain: 'Captain'
}
};
const CaptainSchema = {
name: 'Captain',
properties: {
captain_name: 'string',
ships: { type: 'linkingObjects', objectType: 'Ship', property: 'captain' }
}
};
var realm = new Realm({schema: [ShipSchema, CaptainSchema]});
realm.write(function() {
realm.create('Ship', {
ship_name: 'My Ship',
captain: {
captain_name: 'John Doe'
}
});
});
TestCase.assertEqual(realm.objects('Captain').length, 1);
TestCase.assertEqual(realm.objects('Ship').length, 1);
TestCase.assertEqual(realm.objects('Ship')[0].captain.captain_name, "John Doe");
TestCase.assertEqual(realm.objects('Captain')[0].ships[0].ship_name, "My Ship");
realm.close();
realm = new Realm({schema: [ShipSchema, CaptainSchema], schemaVersion: 1, migration: function(oldRealm, newRealm) {
TestCase.assertThrows(function(e) {
// deleting a model which is target of linkingObjects results in an exception
newRealm.deleteModel('Captain');
console.log(e);
}, "Table is target of cross-table link columns");
}});
TestCase.assertEqual(realm.objects('Captain').length, 1);
TestCase.assertEqual(realm.objects('Ship').length, 1);
realm.close();
realm = new Realm({schema: [ShipSchema, CaptainSchema], schemaVersion: 2, migration: function(oldRealm, newRealm) {
// deleting a model which isn't target of linkingObjects works fine
newRealm.deleteModel('Ship');
}});
TestCase.assertEqual(realm.objects('Captain').length, 1);
TestCase.assertEqual(realm.objects('Ship').length, 0);
TestCase.assertEqual(realm.objects('Captain')[0].ships.length, 0);
realm.close();
},
}; };