diff --git a/lib/src/realm_class.dart b/lib/src/realm_class.dart index 38044f8fb5..b7633a0603 100644 --- a/lib/src/realm_class.dart +++ b/lib/src/realm_class.dart @@ -249,25 +249,39 @@ class Realm implements Finalizable { } } - /// Adds a [RealmObject] to the `Realm`. + /// Adds a [RealmObject] or ingest an [AsymmetricObject]. + /// + /// When adding a [RealmObject] this `Realm` will start managing the object. /// - /// This `Realm` will start managing the [RealmObject]. /// A [RealmObject] instance can be managed only by one `Realm`. /// If the object is already managed by this `Realm`, this method does nothing. - /// This method modifies the object in-place as it becomes managed. Managed instances are persisted and become live objects. + /// This method modifies the object in-place as it becomes managed. Managed instances + /// are persisted and become live objects. + /// /// Returns the same instance as managed. This is just meant as a convenience to enable fluent syntax scenarios. /// /// By setting the [update] flag you can update any existing object with the same primary key. /// Updating only makes sense for objects with primary keys, and is effectively ignored /// otherwise. /// - /// Throws [RealmException] when trying to add objects with the same primary key. + /// Ingesting a [AsymmetricObject] is a write only operation. The ingested objects + /// synchronizes to the App Services backend and are deleted from the device. An + /// [AsymmetricObject] can never be read from the Realm. The [update] flag is + /// ignored when adding [AsymmetricObject]s (always `false`). + /// + /// Throws [RealmException] when trying to add objects with the same primary key, + /// as an already existing object of the same type in the `Realm`. + /// /// Throws [RealmException] if there is no write transaction created with [write]. - T add(T object, {bool update = false}) { + T add(T object, {bool update = false}) { + _add(object, update: object is AsymmetricObject ? false : update); + return object; + } + + void _add(TopLevelObject object, {bool update = false}) { if (object.isManaged) { _ensureManagedByThis(object, 'add object to Realm'); - - return object; + return; } final metadata = _metadata.getByType(object.runtimeType); @@ -275,21 +289,6 @@ class Realm implements Finalizable { final accessor = RealmCoreAccessor(metadata, _isInMigration); object.manage(this, handle, accessor, update); - - return object; - } - - /// Ingest an [AsymmetricObject] to the [Realm]. - /// - /// Ingesting is a write only operation. The ingested objects synchronizes to - /// the App Services backend and are deleted from the device. An [AsymmetricObject] - /// can never be read from the Realm. - void ingest(T object) { - final metadata = _metadata.getByType(object.runtimeType); - final handle = _createObject(object, metadata, false); - - final accessor = RealmCoreAccessor(metadata, _isInMigration); - object.manage(this, handle, accessor, false); } RealmObjectHandle _createObject(RealmObjectBase object, RealmObjectMetadata metadata, bool update) { diff --git a/lib/src/realm_object.dart b/lib/src/realm_object.dart index d860f2b147..0de18e3c79 100644 --- a/lib/src/realm_object.dart +++ b/lib/src/realm_object.dart @@ -454,10 +454,10 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker, Finalizab } /// @nodoc -mixin RealmObject on RealmObjectBase implements RealmObjectMarker {} +sealed class TopLevelObject with RealmEntity, RealmObjectBase {} /// @nodoc -mixin EmbeddedObject on RealmObjectBase implements EmbeddedObjectMarker {} +mixin RealmObject on RealmObjectBase implements RealmObjectMarker, TopLevelObject {} /// Base for any object that can be persisted in a [Realm], but cannot be retrieved, /// hence cannot be modified. @@ -468,7 +468,10 @@ mixin EmbeddedObject on RealmObjectBase implements EmbeddedObjectMarker {} /// /// Use [AsymmetricObject] when you have a write-/only use case. You use it by /// parsing [ObjectType.asymmetricObject] to the [RealmModel] annotation. -mixin AsymmetricObject on RealmObjectBase implements AsymmetricObjectMarker {} +mixin AsymmetricObject on RealmObjectBase implements AsymmetricObjectMarker, TopLevelObject {} + +/// @nodoc +mixin EmbeddedObject on RealmObjectBase implements EmbeddedObjectMarker {} extension EmbeddedObjectExtension on EmbeddedObject { /// Retrieve the [parent] object of this embedded object. diff --git a/test/asymmetric_test.dart b/test/asymmetric_test.dart index 606b572e88..5e6953e173 100644 --- a/test/asymmetric_test.dart +++ b/test/asymmetric_test.dart @@ -64,7 +64,7 @@ Future main([List? args]) async { final oid = ObjectId(); realm.write(() { - realm.ingest(Asymmetric(oid, embeddedObjects: [1, 2, 3].map(Embedded.new))); + realm.add(Asymmetric(oid, embeddedObjects: [1, 2, 3].map(Embedded.new))); }); // Find & query on an Asymmetric object is compile time error, but you can cheat with dynamic @@ -80,14 +80,14 @@ Future main([List? args]) async { final oid = ObjectId(); realm.write(() { - realm.ingest(Asymmetric(oid, embeddedObjects: [1, 2, 3].map(Embedded.new))); - expect(() => realm.ingest(Asymmetric(oid, embeddedObjects: [1, 2, 3, 4].map(Embedded.new))), + realm.add(Asymmetric(oid, embeddedObjects: [1, 2, 3].map(Embedded.new))); + expect(() => realm.add(Asymmetric(oid, embeddedObjects: [1, 2, 3, 4].map(Embedded.new))), throws("Attempting to create an object of type 'Asymmetric' with an existing primary key value")); }); realm.write(() { // okay to ingest again in another transaction, because object already dead to us - realm.ingest(Asymmetric(oid, embeddedObjects: [1, 2, 3, 5].map(Embedded.new))); + realm.add(Asymmetric(oid, embeddedObjects: [1, 2, 3, 5].map(Embedded.new))); }); await realm.syncSession.waitForUpload(); @@ -104,8 +104,8 @@ Future main([List? args]) async { final s = realm.add(Symmetric(ObjectId())); // Since this shenanigan is allowed, I have opened a feature request to allow // direct links on a symmetric objects. See https://github.com/realm/realm-core/issues/6976. - realm.ingest(Asymmetric(ObjectId(), embeddedObjects: [Embedded(1, symmetric: s)])); - realm.ingest(Asymmetric(ObjectId(), embeddedObjects: [Embedded(1, any: RealmValue.from(s))])); + realm.add(Asymmetric(ObjectId(), embeddedObjects: [Embedded(1, symmetric: s)])); + realm.add(Asymmetric(ObjectId(), embeddedObjects: [Embedded(1, any: RealmValue.from(s))])); }); await realm.syncSession.waitForUpload();