diff --git a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/AsymmetricSyncTest.kt b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/AsymmetricSyncTest.kt index 54b6f08d74..a150235d27 100644 --- a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/AsymmetricSyncTest.kt +++ b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/AsymmetricSyncTest.kt @@ -10,9 +10,6 @@ import io.realm.kotlin.mongodb.ext.call import io.realm.kotlin.mongodb.ext.insert import io.realm.kotlin.mongodb.sync.SyncConfiguration import io.realm.kotlin.mongodb.syncSession -import io.realm.kotlin.types.AsymmetricRealmObject -import io.realm.kotlin.types.annotations.PersistedName -import io.realm.kotlin.types.annotations.PrimaryKey import org.mongodb.kbson.ObjectId import kotlin.test.Test import kotlin.test.assertEquals @@ -24,8 +21,12 @@ import kotlin.time.Duration.Companion.seconds // "yourFlexAppId": "YOUR_APP_ID" // } // } -class AsymmetricSyncTest : RealmTest() { +/* +** Snippets used on Stream Data to Atlas, Define, and CRUD pages ** +** Object model defined in Schema.kt ** + */ +class AsymmetricSyncTest : RealmTest() { @OptIn(ExperimentalAsymmetricSyncApi::class, ExperimentalRealmSerializerApi::class) @Test @@ -43,14 +44,23 @@ class AsymmetricSyncTest : RealmTest() { val oid = ObjectId() // :snippet-start: create-asymmetric-object + // Open a write transaction realm.write { - insert(WeatherSensor().apply { + // Create a new asymmetric object + val weatherSensor = WeatherSensor().apply { id = oid //:remove: deviceId = "WX1278UIT" temperatureInFarenheit = 6.7F barometricPressureInHg = 29.65F windSpeedInMph = 2 - }) + } + // Insert the object into the realm with the insert() extension method + insert(weatherSensor) + + // The object is inserted into the realm, then syncs to the + // App Services backend. You CANNOT access the managed + // data locally. + } // :snippet-end: // Add a delay to give the document time to sync diff --git a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/CreateTest.kt b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/CreateTest.kt index 12b32c7f3a..a250d80db4 100644 --- a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/CreateTest.kt +++ b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/CreateTest.kt @@ -2,131 +2,379 @@ package com.mongodb.realm.realmkmmapp import io.realm.kotlin.Realm import io.realm.kotlin.RealmConfiguration -import io.realm.kotlin.ext.query -import io.realm.kotlin.ext.realmDictionaryOf +import io.realm.kotlin.ext.* import io.realm.kotlin.internal.platform.runBlocking -import io.realm.kotlin.query.RealmResults +import io.realm.kotlin.types.MutableRealmInt +import io.realm.kotlin.types.RealmAny +import io.realm.kotlin.types.RealmInstant import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue // :replace-start: { // "terms": { -// "RealmDictionary_": "", -// "RealmSet_": "" +// "ExampleRealmObject_": "", +// "RealmObjectProperties_": "", +// "ExampleEmbeddedObject_": "", +// "ExampleRelationship_": "", +// "ExampleRealmList_": "", +// "ExampleRealmDictionary_": "", +// "ExampleRealmSet_": "", +// "RealmEmbeddedObject_": "" // } // } +/* +** Snippets used on Create page ** +** Object models defined in Schema.kt ** + */ + class CreateTest: RealmTest() { @Test - fun createRealmSetType() { + fun createRealmObject() { runBlocking { - val config = RealmConfiguration.Builder(setOf(RealmSet_Frog::class, RealmSet_Snack::class)) + val config = RealmConfiguration.Builder(setOf(ExampleRealmObject_Frog::class)) .inMemory() .build() val realm = Realm.open(config) Log.v("Successfully opened realm: ${realm.configuration.path}") - - // :snippet-start: create-realm-set + // :snippet-start: create-new-realm-object + // Open a write transaction realm.write { - // Create a Frog object named 'Kermit' - // Add item to the RealmSet using the add() method - val frog = copyToRealm( - RealmSet_Frog().apply { - name = "Kermit" - favoriteSnacks.add(RealmSet_Snack().apply { name = "flies" }) - } - ) - assertEquals(1, frog.favoriteSnacks.size) // :remove: - assertEquals("flies", frog.favoriteSnacks.first().name) // :remove: - println(frog.favoriteSnacks.first().name) // prints "flies" + deleteAll() // :remove: + // Create a new unmanaged Frog object + val frog = ExampleRealmObject_Frog().apply { + name = "Kermit" + age = 42 + owner = "Jim Henson" + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) + + // Work with the managed object ... } // :snippet-end: - // :snippet-start: add-all-to-realm-set realm.write { - val frog = query().find().first() - val snackSet = frog.favoriteSnacks + val deleteFrog = query().find().first() + assertEquals("Kermit", deleteFrog.name) + delete(deleteFrog) + } + realm.close() + } + } - // Create two more RealmSet_Snack objects - val cricketsSnack = copyToRealm( - RealmSet_Snack().apply { - name = "crickets" - } + @Test + fun createEmbeddedObject() { + runBlocking { + val config = RealmConfiguration.Builder( + setOf( + ExampleRelationship_Business::class, + ExampleRelationship_Contact::class, + ExampleRelationship_EmbeddedCountry::class, + ExampleRelationship_EmbeddedAddress::class ) - val wormsSnack = copyToRealm( - RealmSet_Snack().apply { - name = "worms" + ) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + // :snippet-start: create-one-embedded-object + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a parent object with one embedded address + val contact = ExampleRelationship_Contact().apply { + name = "Kermit" + address = ExampleRelationship_EmbeddedAddress().apply { + propertyOwner = ExampleRelationship_Contact().apply { name = "Mr. Frog" } + street = "123 Pond St" + country = ExampleRelationship_EmbeddedCountry().apply { name = "United States" } } - ) + } + // Copy all objects to realm to return a managed instance + copyToRealm(contact) + } + // :snippet-end: + // :snippet-start: create-many-embedded-objects + realm.write { + // Create a parent object with multiple embedded addresses + val localOffice = ExampleRelationship_EmbeddedAddress().apply { + propertyOwner = ExampleRelationship_Contact().apply { name = "Michigan J. Frog" } + street = "456 Lily Pad Ln" + country = ExampleRelationship_EmbeddedCountry().apply { name = "United States" } + } + val remoteOffice = ExampleRelationship_EmbeddedAddress().apply { + propertyOwner = ExampleRelationship_Contact().apply { name = "Mr. Toad" } + street = "789 Leaping Frog Ave" + country = ExampleRelationship_EmbeddedCountry().apply { name = "Ireland" } + } + val business = ExampleRelationship_Business().apply { + name = "Big Frog Corp." + addresses = realmListOf(localOffice, remoteOffice) + } + // Copy all objects to realm to return a managed instance + copyToRealm(business) + } + // :snippet-end: + realm.write { + val deleteContact = query().find().first() + assertEquals("Kermit", deleteContact.name) + delete(deleteContact) + val deleteBusiness = query().find().first() + assertEquals("Big Frog Corp.", deleteBusiness.name) + assertEquals("Michigan J. Frog", deleteBusiness.addresses.first().propertyOwner?.name) + assertEquals("456 Lily Pad Ln", deleteBusiness.addresses.first().street) + assertEquals("789 Leaping Frog Ave", deleteBusiness.addresses.last().street) + assertEquals("Mr. Toad", deleteBusiness.addresses.last().propertyOwner?.name) + delete(deleteBusiness) + } + realm.close() + } + } + + @Test + fun createRealmInstant() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(RealmObjectProperties_Frog::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") - // Add multiple items to the RealmSet using the addAll() method - snackSet.addAll(setOf(cricketsSnack, wormsSnack)) - assertEquals(3, snackSet.size) // :remove: + // :snippet-start: create-realminstant-property + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged Frog object with a RealmInstant property + val frog = RealmObjectProperties_Frog().apply { + name = "Kermit" + // Set an initial value with RealmInstant.from() or RealmInstant.now() + birthdate = RealmInstant.from(1_577_996_800, 0) + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) } // :snippet-end: - realm.writeBlocking { - val frogs = query().find().first() - delete(frogs) + realm.write { + val frog = query().find().first() + assertEquals(1_577_996_800, frog.birthdate?.epochSeconds) + delete(frog) } realm.close() } } @Test - fun createRealmDictionaryType() { + fun createMutableRealmInt() { runBlocking { - val config = RealmConfiguration.Builder( - schema = setOf(RealmDictionary_Frog::class) // Pass the defined class as the object schema - ) + val config = RealmConfiguration.Builder(setOf(RealmObjectProperties_Frog::class)) .inMemory() .build() val realm = Realm.open(config) - Log.v("Successfully opened realm: ${realm.configuration.name}") + Log.v("Successfully opened realm: ${realm.configuration.path}") + // :snippet-start: create-mutablerealm-property + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged Frog object with a MutableRealmInt property + val frog = RealmObjectProperties_Frog().apply { + name = "Michigan J. Frog" + // Set an initial value with MutableRealmInt.create() + fliesEaten = MutableRealmInt.create(200) + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) + } + // :snippet-end: + realm.write { + val frog = query().find().first() + assertEquals(200, frog.fliesEaten?.get()) + frog.fliesEaten?.increment(1) + assertEquals(201, frog.fliesEaten?.get()) + frog.fliesEaten?.decrement(1) + assertEquals(200, frog.fliesEaten?.get()) + delete(frog) + } + realm.close() + } + } + + @Test + fun createRealmAny() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(RealmObjectProperties_Frog::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") - // Delete frogs to make this test successful on consecutive reruns + // :snippet-start: create-realmany-property + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged Frog object with a RealmAny property + val frog = RealmObjectProperties_Frog().apply { + name = "Kermit" + // Set initial values with RealmAny.create() + favoriteThings = realmListOf( + RealmAny.create(42), + RealmAny.create("rainbows"), + RealmAny.create(RealmObjectProperties_Frog().apply { + name = "Kermit Jr." + }) + ) + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) + } + // :snippet-end: realm.write { - // fetch all frogs from the realm - val frogs: RealmResults = this.query().find() - // call delete on the results of a query to delete those objects permanently - delete(frogs) - assertEquals(0, frogs.size) + val frog = query().find().first() + assertEquals(42, frog.favoriteThings.first()?.asInt()) + assertEquals("rainbows", frog.favoriteThings[1]?.asString()) + assertEquals("Kermit Jr.", frog.favoriteThings[2]?.asRealmObject()?.name) + deleteAll() } + realm.close() + } + } - // :snippet-start: create-dictionary + @Test + fun createRealmList(){ + runBlocking { + val config = RealmConfiguration.Builder(setOf( + ExampleRealmList_Frog::class, ExampleRealmList_Pond::class, ExampleEmbeddedObject_EmbeddedForest::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + + // :snippet-start: create-realm-list + // Open a write transaction realm.write { - this.copyToRealm(RealmDictionary_Frog().apply { + deleteAll() // :remove: + // Create a new unmanaged Frog object with a RealmList property + val frog = ExampleRealmList_Frog().apply { name = "Kermit" - favoritePondsByForest = realmDictionaryOf("Hundred Acre Wood" to "Picnic Pond", "Lothlorien" to "Linya") - }) + // Set values for each unmanaged list + favoritePonds.addAll(realmListOf( + ExampleRealmList_Pond().apply { name = "Picnic Pond" }, + ExampleRealmList_Pond().apply { name = "Big Pond" } + )) + favoriteForests.add(ExampleEmbeddedObject_EmbeddedForest().apply { name = "Hundred Acre Wood" }) + favoriteWeather = realmListOf("rain", "snow") + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) } // :snippet-end: - val frogs: RealmResults = realm.query().find() - assertEquals(1, frogs.size) - val thisFrog = frogs.first() - assertEquals(2, thisFrog.favoritePondsByForest.size) + realm.writeBlocking { + val kermit = query("name = $0", "Kermit").find().first() + assertEquals("Picnic Pond", kermit.favoritePonds[0].name) + assertEquals("Big Pond", kermit.favoritePonds[1].name) + assertEquals("Hundred Acre Wood", kermit.favoriteForests[0].name) + assertEquals("rain", kermit.favoriteWeather[0]) + assertEquals("snow", kermit.favoriteWeather[1]) + deleteAll() + } realm.close() } } @Test - fun createRealmDictionaryPercentEncodedDisallowedCharacter() { + fun createRealmSet() { runBlocking { - val config = RealmConfiguration.Builder( - schema = setOf(RealmDictionary_Frog::class) // Pass the defined class as the object schema - ) + val config = RealmConfiguration.Builder(setOf(ExampleRealmSet_Frog::class, ExampleRealmSet_Snack::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + + // :snippet-start: create-realm-set + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged Frog object with RealmSet properties + val frog = ExampleRealmSet_Frog().apply { + name = "Kermit" + // Set initial values to each unmanaged set + favoriteSnacks.addAll(setOf( + ExampleRealmSet_Snack().apply { name = "flies" }, + ExampleRealmSet_Snack().apply { name = "crickets" }, + ExampleRealmSet_Snack().apply { name = "worms" } + )) + favoriteWeather.add("rain") + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) + } + // :snippet-end: + realm.writeBlocking { + val kermit = query("name = $0", "Kermit").find().first() + assertEquals(3, kermit.favoriteSnacks.size) + val snacks = kermit.favoriteSnacks.toList() + assertEquals("flies", snacks[0].name) + assertEquals("crickets", snacks[1].name) + assertEquals("worms", snacks[2].name) + assertTrue(kermit.favoriteWeather.contains("rain")) + deleteAll() + } + realm.close() + } + } + + @Test + fun createRealmDictionaryType() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(ExampleRealmDictionary_Frog::class, ExampleEmbeddedObject_EmbeddedForest::class)) .inMemory() .build() val realm = Realm.open(config) Log.v("Successfully opened realm: ${realm.configuration.name}") - // Delete frogs to make this test successful on consecutive reruns + // :snippet-start: create-dictionary + // Open a write transaction + realm.write { + deleteAll() // :remove: + val frog = ExampleRealmDictionary_Frog().apply { + name = "Kermit" + // Set initial key-values to each unmanaged dictionary + favoriteFriendsByPond = realmDictionaryOf( + "Picnic Pond" to ExampleRealmDictionary_Frog().apply { name = "Froggy Jay" }, + "Big Pond" to ExampleRealmDictionary_Frog().apply { name = "Mr. Toad" } + ) + favoriteTreesInForest["Maple"] = ExampleEmbeddedObject_EmbeddedForest().apply { name = "Hundred Acre Wood" } + favoritePondsByForest.putAll(mapOf( + "Silver Pond" to "Big Forest", + "Big Lake" to "Elm Wood", + "Trout Pond" to "Sunny Wood" + )) + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) + } + // :snippet-end: realm.write { - // fetch all frogs from the realm - val frogs: RealmResults = this.query().find() - // call delete on the results of a query to delete those objects permanently - delete(frogs) - assertEquals(0, frogs.size) + val frogs = query().find().first() + assertEquals("Froggy Jay", frogs.favoriteFriendsByPond["Picnic Pond"]?.name) + assertEquals("Maple", frogs.favoriteTreesInForest.keys.first()) + assertEquals("Big Forest", frogs.favoritePondsByForest["Silver Pond"]) + deleteAll() } + realm.close() + } + } + + @Test + fun createRealmDictionaryPercentEncodedDisallowedCharacter() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(ExampleRealmDictionary_Frog::class, ExampleEmbeddedObject_EmbeddedForest::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.name}") // :snippet-start: percent-encode-disallowed-characters // Percent encode . or $ characters to use them in map keys @@ -138,19 +386,181 @@ class CreateTest: RealmTest() { // Not testing encoding/decoding here because (Dachary) could not figure out how to add java.net as a dependency // This functionality seems to be provided by java.net.URLEncoder/URLDecoder realm.write { - this.copyToRealm(RealmDictionary_Frog().apply { + deleteAll() + val frog = ExampleRealmDictionary_Frog().apply { + name = "Kermit" + favoriteTreesInForest[encodedMapKey] = ExampleEmbeddedObject_EmbeddedForest().apply { name = "Hundred Acre Wood" } + } + val savedEncodedMapKey = frog.favoriteTreesInForest.keys.first() + assertEquals(encodedMapKey, savedEncodedMapKey) + deleteAll() + } + realm.close() + } + } + + @Test + fun createToOneRelationship() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(ExampleRelationship_Frog::class, ExampleRelationship_Pond::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + // :snippet-start: create-to-one-realm-relationship + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged Frog object with to-one relationship with a Realm object + val frog = ExampleRelationship_Frog().apply { + name = "Kermit" + age = 12 + favoritePond = ExampleRelationship_Pond().apply { name = "Picnic Pond" } + bestFriend = ExampleRelationship_Frog().apply { name = "Froggy Jay" } + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) + } + // :snippet-end: + realm.write { + val kermit = query("name == $0", "Kermit").find().first() + assertEquals("Picnic Pond", kermit.favoritePond?.name) + val froggyJay = query("name == $0", "Froggy Jay").find().first() + assertEquals(froggyJay, kermit.bestFriend) + deleteAll() + } + realm.close() + } + } + + @Test + fun createToManyRelationship() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(ExampleRelationship_Forest::class, ExampleRelationship_Frog::class, ExampleRelationship_Pond::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + // :snippet-start: create-to-many-realm-relationship + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged Forest object with to-many relationship with multiple Realm objects + val forest = ExampleRelationship_Forest().apply { + name = "Froggy Forest" + frogsThatLiveHere = realmSetOf( + ExampleRelationship_Frog().apply { name = "Kermit" }, + ExampleRelationship_Frog().apply { name = "Froggy Jay" } + ) + nearbyPonds = realmListOf( + ExampleRelationship_Pond().apply { name = "Small Picnic Pond" }, + ExampleRelationship_Pond().apply { name = "Big Pond" } + ) + } + // Copy all objects to realm to return managed instances + copyToRealm(forest) + } + // :snippet-end: + realm.write { + val forest = query().find().first() + assertEquals(2, forest.frogsThatLiveHere.size) + assertEquals(2, forest.nearbyPonds.size) + val kermit = query("name == $0", "Kermit").find().first() + assertTrue(forest.frogsThatLiveHere.contains(kermit)) + val bigPond = query("name == $0", "Big Pond").find().first() + assertTrue(forest.nearbyPonds.contains(bigPond)) + deleteAll() + } + realm.close() + } + } + + @Test + fun createInverseRelationship() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(ExampleRelationship_User::class, ExampleRelationship_Post::class)) + .inMemory() + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + // :snippet-start: create-inverse-realm-relationship + // Open a write transaction + realm.write { + deleteAll() // :remove: + // Create a new unmanaged User object with to-many relationship with multiple Realm objects + val post1 = ExampleRelationship_Post().apply { + title = "Forest Life" + } + val post2 = ExampleRelationship_Post().apply { + title = "Top Ponds of the Year!" + } + + val user = ExampleRelationship_User().apply { name = "Kermit" - favoritePondsByForest = realmDictionaryOf(encodedMapKey to "Picnic Pond") + posts = realmListOf(post1, post2) + } + // Copy all objects to realm to return managed instances + copyToRealm(user) + } + // :snippet-end: + realm.write { + val user = query().find().first() + assertEquals(2, user.posts.size) + val post1 = query("title == $0", "Forest Life").find().first() + val post2 = query("title == $0", "Top Ponds of the Year!").find().first() + assertTrue(user.posts.containsAll(listOf(post1, post2))) + assertTrue(post1.user.contains(user)) + deleteAll() + } + realm.close() + } + } + + @Test + fun createUnmanagedCopy() { + runBlocking { + val config = RealmConfiguration.Builder(setOf(ExampleRealmObject_Pond::class, ExampleRealmObject_Frog::class)) + .inMemory() + .name("create-unmanaged-copy") + .build() + val realm = Realm.open(config) + Log.v("Successfully opened realm: ${realm.configuration.path}") + + realm.writeBlocking { + copyToRealm(ExampleRealmObject_Pond().apply { + name = "Big Pond" + frogsThatLiveHere = realmListOf( + ExampleRealmObject_Frog().apply { name = "Kermit" }, + ExampleRealmObject_Frog().apply { name = "Froggy Jay" } + ) }) } - val frogs: RealmResults = realm.query().find() - val thisFrog = frogs.first() - val savedEncodedMapKey = thisFrog.favoritePondsByForest.keys.first() - assertEquals(encodedMapKey, savedEncodedMapKey) + // :snippet-start: create-unmanaged-copy + // Open a write transaction + realm.writeBlocking { + // Fetch the managed object you want to copy + val managedPond = query("name == $0", "Big Pond").find().first() + assertTrue(managedPond.isManaged()) + + // Create an unmanaged copy of the object + val unmanagedPond = copyFromRealm(managedPond) + assertFalse(unmanagedPond.isManaged()) + Log.v("Unmanaged pond name: ${unmanagedPond.name}") + + // Confirm the unmanaged copy contains all elements in the copied object's RealmList + val unmanagedFrogs = unmanagedPond.frogsThatLiveHere + assertFalse(unmanagedFrogs[0].isManaged()) + assertFalse(unmanagedFrogs[1].isManaged()) + assertEquals(2, unmanagedFrogs.size) + Log.v("Unmanaged frogs: ${unmanagedFrogs[0].name}, ${unmanagedFrogs[1].name}") + } + // :snippet-end: + realm.write { + deleteAll() + } realm.close() } } } - // :replace-end: \ No newline at end of file diff --git a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/DataTypesTest.kt b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/DataTypesTest.kt index 6dd6a06d18..fb3bb1eace 100644 --- a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/DataTypesTest.kt +++ b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/DataTypesTest.kt @@ -4,11 +4,9 @@ import io.realm.kotlin.Realm import io.realm.kotlin.RealmConfiguration import io.realm.kotlin.ext.parent import io.realm.kotlin.ext.query -import io.realm.kotlin.ext.realmListOf import io.realm.kotlin.internal.platform.runBlocking import io.realm.kotlin.query.RealmResults import io.realm.kotlin.types.EmbeddedRealmObject -import io.realm.kotlin.types.RealmList import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.annotations.PrimaryKey import kotlinx.coroutines.Deferred @@ -17,36 +15,49 @@ import org.mongodb.kbson.ObjectId import kotlin.test.Test import kotlin.test.assertEquals + +/* +** Leaving these here until the Read, Update, and Delete pages are updated +* to use the new object model and this page can be deleted +* +* See the Schema.kt file for the new object model and CreateTest.kt for new tested Create snippets + */ + +class EmbeddedAddress : EmbeddedRealmObject { + var street: String? = null + var city: String? = null + var state: String? = null + var postalCode: String? = null +} + +class Contact : RealmObject { + @PrimaryKey + var _id: ObjectId = ObjectId() + var name: String = "" + var address: EmbeddedAddress? = null +} + class DataTypesTest : RealmTest() { @Test fun createEmbeddedObject() { runBlocking { - // :snippet-start: open-realm-embedded-object - // Include parent and embedded object classes in schema val config = RealmConfiguration.Builder( setOf(Contact::class, EmbeddedAddress::class) ) .build() val realm = Realm.open(config) - // :snippet-end: - - // :snippet-start: create-embedded-object - // Create a parent object with one embedded address realm.write { val contact = copyToRealm(Contact()) - contact.apply { - name = "Nick Riviera" - - // Embed the address in the contact object - address = EmbeddedAddress().apply { - street = "123 Fake St" - city = "Some Town" - state = "MA" - postalCode = "12345" - } + contact.apply { + name = "Nick Riviera" + address = EmbeddedAddress().apply { + street = "123 Fake St" + city = "Some Town" + state = "MA" + postalCode = "12345" } + } } - // :snippet-end: val asyncCall: Deferred = async { val address: EmbeddedAddress = realm.query().find().first() @@ -74,22 +85,22 @@ class DataTypesTest : RealmTest() { } // :snippet-end: - // :snippet-start: overwrite-embedded-object - // Overwrite the embedded object in a write transaction - realm.write { - // Fetch the parent object - val parentObject: Contact = - realm.query("name == 'Nick Riviera'").find().first() - - // Overwrite the embedded object (deletes the existing object) - parentObject.address = EmbeddedAddress().apply { - street = "202 Coconut Court" - city = "Los Angeles" - state = "CA" - postalCode = "90210" + // :snippet-start: overwrite-embedded-object + // Overwrite the embedded object in a write transaction + realm.write { + // Fetch the parent object + val parentObject: Contact = + realm.query("name == 'Nick Riviera'").find().first() + + // Overwrite the embedded object (deletes the existing object) + parentObject.address = EmbeddedAddress().apply { + street = "202 Coconut Court" + city = "Los Angeles" + state = "CA" + postalCode = "90210" + } } - } - // :snippet-end: + // :snippet-end: } asyncCall.cancel() @@ -154,15 +165,15 @@ class DataTypesTest : RealmTest() { realm.write { val contact1 = copyToRealm(Contact()) - contact1.apply { - name = "Marvin Monroe" - address = EmbeddedAddress().apply { - street = "123 Fake St" - city = "Some Town" - state = "MA" - postalCode = "12345" - } + contact1.apply { + name = "Marvin Monroe" + address = EmbeddedAddress().apply { + street = "123 Fake St" + city = "Some Town" + state = "MA" + postalCode = "12345" } + } val contact2 = copyToRealm(Contact()) contact2.apply { name = "Nick Riviera" diff --git a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/Schema.kt b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/Schema.kt index 16775ee803..f712065a5b 100644 --- a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/Schema.kt +++ b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/Schema.kt @@ -13,8 +13,12 @@ import org.mongodb.kbson.ObjectId // :replace-start: { // "terms": { // "ExampleRealmObject_": "", +// "ExampleEmbeddedObject_": "", +// "RealmObjectProperties_": "", +// "RealmEmbeddedObject_": "", // "ExampleRelationship_": "", // "ExampleEmbeddedRelationship_": "", +// "ExampleRealmList_": "", // "RealmList_": "", // "ExampleRealmDictionary_": "", // "RealmDictionary_": "", @@ -40,34 +44,43 @@ class ExampleRealmObject_Frog : RealmObject { // Empty constructor required by R var owner: String? = null } // :snippet-end: -class ExampleRealmObject_EmbeddedForest : EmbeddedRealmObject { + +class ExampleRealmObject_Pond : RealmObject { + var _id: ObjectId = ObjectId() + var name: String = "" + var frogsThatLiveHere: RealmList = realmListOf() +} +class ExampleEmbeddedObject_EmbeddedForest : EmbeddedRealmObject { var id: ObjectId = ObjectId() var name: String = "" } + // ** Tested in Create, Read, Update, and Delete.kt files ** + +// :snippet-start: create-realm-properties +class RealmObjectProperties_Frog : RealmObject { + @PrimaryKey + var _id: ObjectId = ObjectId() + var name: String = "" + var birthdate: RealmInstant? = null + var fliesEaten: MutableRealmInt? = null + var favoriteThings: RealmList = realmListOf() +} +// :snippet-end: + + // :snippet-start: define-embedded-object // Implements `EmbeddedRealmObject` interface -class EmbeddedAddress : EmbeddedRealmObject { +class ExampleEmbeddedObject_EmbeddedAddress : EmbeddedRealmObject { // CANNOT have primary key var street: String? = null var city: String? = null var state: String? = null var postalCode: String? = null + var propertyOwner: ExampleRelationship_Contact? = null } // :snippet-end: -class Contact : RealmObject { - @PrimaryKey - var _id: ObjectId = ObjectId() - var name: String = "" - var address: EmbeddedAddress? = null -} -class Business : RealmObject { - @PrimaryKey - var _id: ObjectId = ObjectId() - var name: String = "" - var addresses: RealmList = realmListOf() -} // ** Tested in AsymmetricSyncTest.kt ** // :snippet-start: define-asymmetric-model @@ -86,18 +99,18 @@ class WeatherSensor : AsymmetricRealmObject { // :snippet-start: define-a-realm-list // RealmList can be any supported primitive // or BSON type, a RealmObject, or an EmbeddedRealmObject -class RealmList_Frog : RealmObject { +class ExampleRealmList_Frog : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // List of RealmObject type (CANNOT be nullable) - var favoritePonds: RealmList = realmListOf() + var favoritePonds: RealmList = realmListOf() // List of EmbeddedRealmObject type (CANNOT be nullable) - var favoriteForests: RealmList = realmListOf() + var favoriteForests: RealmList = realmListOf() // List of primitive type (can be nullable) var favoriteWeather: RealmList = realmListOf() } -class RealmList_Pond : RealmObject { +class ExampleRealmList_Pond : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" } @@ -143,7 +156,7 @@ class ExampleRealmDictionary_Frog : RealmObject { // Dictionary of RealmObject type (value MUST be nullable) var favoriteFriendsByPond: RealmDictionary = realmDictionaryOf() // Dictionary of EmbeddedRealmObject type (value MUST be nullable) - var favoriteTreesInForest: RealmDictionary = realmDictionaryOf() + var favoriteTreesInForest: RealmDictionary = realmDictionaryOf() // Dictionary of primitive type (value can be nullable) var favoritePondsByForest: RealmDictionary = realmDictionaryOf() } @@ -228,6 +241,7 @@ class ExampleRelationship_Contact : RealmObject { } class ExampleRelationship_EmbeddedAddress : EmbeddedRealmObject { + var propertyOwner: ExampleRelationship_Contact? = null var street: String? = "" // Embed another EmbeddedRealmObject type var country: ExampleRelationship_EmbeddedCountry? = null @@ -274,7 +288,6 @@ class ExampleEmbeddedRelationship_Post : EmbeddedRealmObject { } // :snippet-end: - /* ******** Property Annotations page examples ********* */ @@ -315,4 +328,4 @@ class Frog : RealmObject { // :snippet-end: -// :replace-end: +// :replace-end: \ No newline at end of file diff --git a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/SchemaTest.kt b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/SchemaTest.kt index ce510d32c8..c6d1159215 100644 --- a/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/SchemaTest.kt +++ b/examples/kotlin/shared/src/commonTest/kotlin/com/mongodb/realm/realmkmmapp/SchemaTest.kt @@ -68,17 +68,7 @@ class SchemaTest : RealmTest() { @Test fun createRealmObjectsTest() { runBlocking { - val config = RealmConfiguration.Builder( - setOf( - ExampleRealmObject_Frog::class, - ExampleRealmSet_Frog::class, - ExampleRealmSet_Snack::class, - ExampleRealmDictionary_Frog::class, - ExampleRealmObject_EmbeddedForest::class, - RealmList_Frog::class, - RealmList_Pond::class - ) - ) + val config = RealmConfiguration.Builder(setOf(ExampleRealmObject_Frog::class, ExampleRealmSet_Frog::class, ExampleRealmSet_Snack::class, ExampleRealmDictionary_Frog::class, ExampleEmbeddedObject_EmbeddedForest::class, ExampleRealmList_Frog::class, ExampleRealmList_Pond::class)) .inMemory() .build() val realm = Realm.open(config) @@ -100,30 +90,30 @@ class SchemaTest : RealmTest() { assertEquals(0, query().find().size) // create realm list object - copyToRealm(RealmList_Frog().apply { + copyToRealm(ExampleRealmList_Frog().apply { name = "Timerk" - favoritePonds.add(RealmList_Pond().apply { + favoritePonds.add(ExampleRealmList_Pond().apply { name = "Pond1" }) - favoritePonds.add(RealmList_Pond().apply { + favoritePonds.add(ExampleRealmList_Pond().apply { name = "Pond2" }) - favoriteForests.add(ExampleRealmObject_EmbeddedForest().apply { + favoriteForests.add(ExampleEmbeddedObject_EmbeddedForest().apply { name = "Forest1" }) - favoriteForests.add(ExampleRealmObject_EmbeddedForest().apply { + favoriteForests.add(ExampleEmbeddedObject_EmbeddedForest().apply { name = "Forest2" }) favoriteWeather.add("rain") favoriteWeather.add("snow") }) - val realmListFrog = query().find().first() + val realmListFrog = query().find().first() assertEquals("Timerk", realmListFrog.name) assertEquals(2, realmListFrog.favoritePonds.size) assertEquals(2, realmListFrog.favoriteForests.size) assertEquals(2, realmListFrog.favoriteWeather.size) delete(realmListFrog) - assertEquals(0, query().find().size) + assertEquals(0, query().find().size) // create realm set object copyToRealm(ExampleRealmSet_Frog().apply { @@ -149,7 +139,7 @@ class SchemaTest : RealmTest() { favoriteFriendsByPond["Pond1"] = ExampleRealmDictionary_Frog().apply { name = "Frog1" } - favoriteTreesInForest["Forest1"] = ExampleRealmObject_EmbeddedForest().apply { + favoriteTreesInForest["Forest1"] = ExampleEmbeddedObject_EmbeddedForest().apply { name = "Tree1" } favoritePondsByForest["Forest2"] = "Pond1" diff --git a/snooty.toml b/snooty.toml index 5fcc9f0cb8..31198ed77a 100644 --- a/snooty.toml +++ b/snooty.toml @@ -50,7 +50,6 @@ toc_landing_pages = [ "/sdk/kotlin", "/sdk/kotlin/app-services", "/sdk/kotlin/realm-database", - "/sdk/kotlin/realm-database/write-transactions", "/sdk/kotlin/sync", "/sdk/web", "/sdk/dotnet", diff --git a/source/examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt b/source/examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt index 12c339342f..3fb885c9b1 100644 --- a/source/examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt +++ b/source/examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt @@ -1,8 +1,17 @@ +// Open a write transaction realm.write { - insert(WeatherSensor().apply { + // Create a new asymmetric object + val weatherSensor = WeatherSensor().apply { deviceId = "WX1278UIT" temperatureInFarenheit = 6.7F barometricPressureInHg = 29.65F windSpeedInMph = 2 - }) + } + // Insert the object into the realm with the insert() extension method + insert(weatherSensor) + +// The object is inserted into the realm, then syncs to the +// App Services backend. You CANNOT access the managed +// data locally. + } diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-dictionary.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-dictionary.kt index 26435c5733..84d3f58bfa 100644 --- a/source/examples/generated/kotlin/CreateTest.snippet.create-dictionary.kt +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-dictionary.kt @@ -1,6 +1,19 @@ +// Open a write transaction realm.write { - this.copyToRealm(Frog().apply { + val frog = Frog().apply { name = "Kermit" - favoritePondsByForest = realmDictionaryOf("Hundred Acre Wood" to "Picnic Pond", "Lothlorien" to "Linya") - }) + // Set initial key-values to each unmanaged dictionary + favoriteFriendsByPond = realmDictionaryOf( + "Picnic Pond" to Frog().apply { name = "Froggy Jay" }, + "Big Pond" to Frog().apply { name = "Mr. Toad" } + ) + favoriteTreesInForest["Maple"] = EmbeddedForest().apply { name = "Hundred Acre Wood" } + favoritePondsByForest.putAll(mapOf( + "Silver Pond" to "Big Forest", + "Big Lake" to "Elm Wood", + "Trout Pond" to "Sunny Wood" + )) + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) } diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-embedded-object.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-embedded-object.kt new file mode 100644 index 0000000000..ba3fbcc716 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-embedded-object.kt @@ -0,0 +1,44 @@ +// Open a write transaction +realm.write { + // Create a parent object with one embedded address + val contact = RealmObject_Contact().apply { + name = "Kermit" + address = ExampleEmbeddedObject_EmbeddedAddress().apply { + street = "123 Pond St" + city = "Big Forest" + state = "MA" + postalCode = "12345" + propertyOwner = RealmObject_Contact().apply { + name = "Mr. Frog" + } + } + } + // Copy the object to realm to return a managed instance + copyToRealm(contact) + + // Create a parent object with multiple embedded addresses + val localOffice = ExampleEmbeddedObject_EmbeddedAddress().apply { + street = "456 Lily Pad Ln" + city = "Small Village" + state = "MA" + postalCode = "12345" + propertyOwner = RealmObject_Contact().apply { + name = "Michigan J. Frog" + } + } + val remoteOffice = ExampleEmbeddedObject_EmbeddedAddress().apply { + street = "789 Leaping Frog Ave" + city = "Big City" + state = "MA" + postalCode = "12345" + propertyOwner = RealmObject_Contact().apply { + name = "Mr. Toad" + } + } + val business = RealmObject_Business().apply { + name = "Big Frog Corp." + addresses = realmListOf(localOffice, remoteOffice) + } + // Copy the object to realm to return a managed instance + copyToRealm(business) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-inverse-realm-relationship.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-inverse-realm-relationship.kt new file mode 100644 index 0000000000..72cfc4d55d --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-inverse-realm-relationship.kt @@ -0,0 +1,17 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged User object with to-many relationship with multiple Realm objects + val post1 = Post().apply { + title = "Forest Life" + } + val post2 = Post().apply { + title = "Top Ponds of the Year!" + } + + val user = User().apply { + name = "Kermit" + posts = realmListOf(post1, post2) + } + // Copy all objects to realm to return managed instances + copyToRealm(user) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-many-embedded-objects.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-many-embedded-objects.kt new file mode 100644 index 0000000000..1d75b86cb7 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-many-embedded-objects.kt @@ -0,0 +1,19 @@ +realm.write { + // Create a parent object with multiple embedded addresses + val localOffice = EmbeddedAddress().apply { + propertyOwner = Contact().apply { name = "Michigan J. Frog" } + street = "456 Lily Pad Ln" + country = EmbeddedCountry().apply { name = "United States" } + } + val remoteOffice = EmbeddedAddress().apply { + propertyOwner = Contact().apply { name = "Mr. Toad" } + street = "789 Leaping Frog Ave" + country = EmbeddedCountry().apply { name = "Ireland" } + } + val business = Business().apply { + name = "Big Frog Corp." + addresses = realmListOf(localOffice, remoteOffice) + } + // Copy all objects to realm to return a managed instance + copyToRealm(business) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-mutablerealm-property.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-mutablerealm-property.kt new file mode 100644 index 0000000000..eded6c65ad --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-mutablerealm-property.kt @@ -0,0 +1,11 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Frog object with a MutableRealmInt property + val frog = Frog().apply { + name = "Michigan J. Frog" + // Set an initial value with MutableRealmInt.create() + fliesEaten = MutableRealmInt.create(200) + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-new-realm-object.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-new-realm-object.kt new file mode 100644 index 0000000000..df9919c6e5 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-new-realm-object.kt @@ -0,0 +1,13 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Frog object + val frog = Frog().apply { + name = "Kermit" + age = 42 + owner = "Jim Henson" + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) + + // Work with the managed object ... +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-one-embedded-object.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-one-embedded-object.kt new file mode 100644 index 0000000000..5564007eaa --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-one-embedded-object.kt @@ -0,0 +1,14 @@ +// Open a write transaction +realm.write { + // Create a parent object with one embedded address + val contact = Contact().apply { + name = "Kermit" + address = EmbeddedAddress().apply { + propertyOwner = Contact().apply { name = "Mr. Frog" } + street = "123 Pond St" + country = EmbeddedCountry().apply { name = "United States" } + } + } + // Copy all objects to realm to return a managed instance + copyToRealm(contact) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-realm-list.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-realm-list.kt new file mode 100644 index 0000000000..8fa9fef3c3 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-realm-list.kt @@ -0,0 +1,16 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Frog object with a RealmList property + val frog = Frog().apply { + name = "Kermit" + // Set values for each unmanaged list + favoritePonds.addAll(realmListOf( + Pond().apply { name = "Picnic Pond" }, + Pond().apply { name = "Big Pond" } + )) + favoriteForests.add(EmbeddedForest().apply { name = "Hundred Acre Wood" }) + favoriteWeather = realmListOf("rain", "snow") + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-realm-set.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-realm-set.kt index b40e5ad104..61ce3c8bc7 100644 --- a/source/examples/generated/kotlin/CreateTest.snippet.create-realm-set.kt +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-realm-set.kt @@ -1,11 +1,16 @@ +// Open a write transaction realm.write { - // Create a Frog object named 'Kermit' - // Add item to the RealmSet using the add() method - val frog = copyToRealm( - Frog().apply { - name = "Kermit" - favoriteSnacks.add(Snack().apply { name = "flies" }) - } - ) - println(frog.favoriteSnacks.first().name) // prints "flies" + // Create a new unmanaged Frog object with RealmSet properties + val frog = Frog().apply { + name = "Kermit" + // Set initial values to each unmanaged set + favoriteSnacks.addAll(setOf( + Snack().apply { name = "flies" }, + Snack().apply { name = "crickets" }, + Snack().apply { name = "worms" } + )) + favoriteWeather.add("rain") + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) } diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-realmany-property.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-realmany-property.kt new file mode 100644 index 0000000000..1db35fe2b9 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-realmany-property.kt @@ -0,0 +1,17 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Frog object with a RealmAny property + val frog = Frog().apply { + name = "Kermit" + // Set initial values with RealmAny.create() + favoriteThings = realmListOf( + RealmAny.create(42), + RealmAny.create("rainbows"), + RealmAny.create(Frog().apply { + name = "Kermit Jr." + }) + ) + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-realminstant-property.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-realminstant-property.kt new file mode 100644 index 0000000000..0de8121b60 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-realminstant-property.kt @@ -0,0 +1,11 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Frog object with a RealmInstant property + val frog = Frog().apply { + name = "Kermit" + // Set an initial value with RealmInstant.from() or RealmInstant.now() + birthdate = RealmInstant.from(1_577_996_800, 0) + } + // Copy the object to realm to return a managed instance + copyToRealm(frog) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-to-many-realm-relationship.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-to-many-realm-relationship.kt new file mode 100644 index 0000000000..64e4b08d12 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-to-many-realm-relationship.kt @@ -0,0 +1,17 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Forest object with to-many relationship with multiple Realm objects + val forest = Forest().apply { + name = "Froggy Forest" + frogsThatLiveHere = realmSetOf( + Frog().apply { name = "Kermit" }, + Frog().apply { name = "Froggy Jay" } + ) + nearbyPonds = realmListOf( + Pond().apply { name = "Small Picnic Pond" }, + Pond().apply { name = "Big Pond" } + ) + } + // Copy all objects to realm to return managed instances + copyToRealm(forest) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-to-one-realm-relationship.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-to-one-realm-relationship.kt new file mode 100644 index 0000000000..ba0c92c7c4 --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-to-one-realm-relationship.kt @@ -0,0 +1,12 @@ +// Open a write transaction +realm.write { + // Create a new unmanaged Frog object with to-one relationship with a Realm object + val frog = Frog().apply { + name = "Kermit" + age = 12 + favoritePond = Pond().apply { name = "Picnic Pond" } + bestFriend = Frog().apply { name = "Froggy Jay" } + } + // Copy all objects to realm to return managed instances + copyToRealm(frog) +} diff --git a/source/examples/generated/kotlin/CreateTest.snippet.create-unmanaged-copy.kt b/source/examples/generated/kotlin/CreateTest.snippet.create-unmanaged-copy.kt new file mode 100644 index 0000000000..e2364acb6f --- /dev/null +++ b/source/examples/generated/kotlin/CreateTest.snippet.create-unmanaged-copy.kt @@ -0,0 +1,18 @@ +// Open a write transaction +realm.writeBlocking { + // Fetch the managed object you want to copy + val managedPond = query("name == $0", "Big Pond").find().first() + assertTrue(managedPond.isManaged()) + + // Create an unmanaged copy of the object + val unmanagedPond = copyFromRealm(managedPond) + assertFalse(unmanagedPond.isManaged()) + Log.v("Unmanaged pond name: ${unmanagedPond.name}") + + // Confirm the unmanaged copy contains all elements in the copied object's RealmList + val unmanagedFrogs = unmanagedPond.frogsThatLiveHere + assertFalse(unmanagedFrogs[0].isManaged()) + assertFalse(unmanagedFrogs[1].isManaged()) + assertEquals(2, unmanagedFrogs.size) + Log.v("Unmanaged frogs: ${unmanagedFrogs[0].name}, ${unmanagedFrogs[1].name}") +} diff --git a/source/examples/generated/kotlin/DataTypesTest.snippet.create-embedded-object.kt b/source/examples/generated/kotlin/DataTypesTest.snippet.create-embedded-object.kt deleted file mode 100644 index 3fcb143ba7..0000000000 --- a/source/examples/generated/kotlin/DataTypesTest.snippet.create-embedded-object.kt +++ /dev/null @@ -1,15 +0,0 @@ -// Create a parent object with one embedded address -realm.write { - val contact = copyToRealm(Contact()) - contact.apply { - name = "Nick Riviera" - - // Embed the address in the contact object - address = EmbeddedAddress().apply { - street = "123 Fake St" - city = "Some Town" - state = "MA" - postalCode = "12345" - } - } -} diff --git a/source/examples/generated/kotlin/DataTypesTest.snippet.embedded-object-model.kt b/source/examples/generated/kotlin/DataTypesTest.snippet.embedded-object-model.kt deleted file mode 100644 index 04646ba85b..0000000000 --- a/source/examples/generated/kotlin/DataTypesTest.snippet.embedded-object-model.kt +++ /dev/null @@ -1,26 +0,0 @@ -// Implements `EmbeddedRealmObject` interface -class Address() : EmbeddedRealmObject { - // (cannot have primary key) - var street: String? = null - var city: String? = null - var state: String? = null - var postalCode: String? = null -} - -// Define an object containing one embedded object -class Contact : RealmObject { - @PrimaryKey - var _id: ObjectId = ObjectId() - var name: String = "" - // Embed a single object (must be optional) - var address: Address? = null -} - -// Define an object containing an array of embedded objects -class Business : RealmObject { - @PrimaryKey - var _id: ObjectId = ObjectId() - var name: String = "" - // Embed an array of objects (cannot be null) - var addresses: RealmList
= realmListOf() -} diff --git a/source/examples/generated/kotlin/DataTypesTest.snippet.open-realm-embedded-object.kt b/source/examples/generated/kotlin/DataTypesTest.snippet.open-realm-embedded-object.kt deleted file mode 100644 index cd58cfaad4..0000000000 --- a/source/examples/generated/kotlin/DataTypesTest.snippet.open-realm-embedded-object.kt +++ /dev/null @@ -1,6 +0,0 @@ -// Include parent and embedded object classes in schema -val config = RealmConfiguration.Builder( - setOf(Contact::class, EmbeddedAddress::class) -) - .build() -val realm = Realm.open(config) diff --git a/source/examples/generated/kotlin/Schema.snippet.create-realm-properties.kt b/source/examples/generated/kotlin/Schema.snippet.create-realm-properties.kt new file mode 100644 index 0000000000..d3c00ca838 --- /dev/null +++ b/source/examples/generated/kotlin/Schema.snippet.create-realm-properties.kt @@ -0,0 +1,8 @@ +class Frog : RealmObject { + @PrimaryKey + var _id: ObjectId = ObjectId() + var name: String = "" + var birthdate: RealmInstant? = null + var fliesEaten: MutableRealmInt? = null + var favoriteThings: RealmList = realmListOf() +} diff --git a/source/examples/generated/kotlin/Schema.snippet.define-embedded-object.kt b/source/examples/generated/kotlin/Schema.snippet.define-embedded-object.kt index 6267a80b36..cda9083595 100644 --- a/source/examples/generated/kotlin/Schema.snippet.define-embedded-object.kt +++ b/source/examples/generated/kotlin/Schema.snippet.define-embedded-object.kt @@ -5,4 +5,5 @@ class EmbeddedAddress : EmbeddedRealmObject { var city: String? = null var state: String? = null var postalCode: String? = null + var propertyOwner: Contact? = null } diff --git a/source/examples/generated/kotlin/Schema.snippet.define-to-one-embedded-relationship.kt b/source/examples/generated/kotlin/Schema.snippet.define-to-one-embedded-relationship.kt index 2363193279..caa5ff2646 100644 --- a/source/examples/generated/kotlin/Schema.snippet.define-to-one-embedded-relationship.kt +++ b/source/examples/generated/kotlin/Schema.snippet.define-to-one-embedded-relationship.kt @@ -8,6 +8,7 @@ class Contact : RealmObject { } class EmbeddedAddress : EmbeddedRealmObject { + var propertyOwner: Contact? = null var street: String? = "" // Embed another EmbeddedRealmObject type var country: EmbeddedCountry? = null diff --git a/source/sdk/kotlin/realm-database/crud.txt b/source/sdk/kotlin/realm-database/crud.txt new file mode 100644 index 0000000000..e2b40f054f --- /dev/null +++ b/source/sdk/kotlin/realm-database/crud.txt @@ -0,0 +1,21 @@ +.. _kotlin-read-write-data: + +============================== +Read & Write Data - Kotlin SDK +============================== + +.. toctree:: + :titlesonly: + + Create + Read + Update + Delete + +The following pages contain information about how to read and write data +within a realm using the Realm Kotlin SDK: + +- :ref:`` +- :ref:`` +- :ref:`` +- :ref:`` diff --git a/source/sdk/kotlin/realm-database/crud/create.txt b/source/sdk/kotlin/realm-database/crud/create.txt index 150756d1fa..cb512d4f90 100644 --- a/source/sdk/kotlin/realm-database/crud/create.txt +++ b/source/sdk/kotlin/realm-database/crud/create.txt @@ -10,21 +10,114 @@ Create Realm Objects - Kotlin SDK :depth: 2 :class: singlecol -.. note:: +This page describes how to create a new object in a local or synced realm +using the Kotlin SDK. To learn more about Realm objects and how to define them, +refer to :ref:``. + +You can create objects whose object type is included in the +realm schema when you open the realm. +For more information, refer to +:ref:`` or :ref:``. + +.. note:: Write to a Synced Realm + + The syntax to write a new object to a realm is the same for a local or + a synced realm. However, there are additional considerations that determine + whether the write operation in a synced realm is successful. For more + information, refer to :ref:``. + +.. _kotlin-write-transactions: +.. _kotlin-open-a-transaction: + +Write Transactions +------------------ + +Realm handles writes in terms of transactions. All writes must happen +within a transaction. + +A **transaction** is a list of read and write operations that +Realm treats as a single indivisible operation: either *all* of the +operations succeed or *none* of the operations in the transaction +take effect. + +Realm represents each transaction as a callback function +that contains zero or more read and write operations. To run +a transaction, you define a transaction callback and pass it to +the realm's +`write() <{+kotlin-local-prefix+}io.realm.kotlin/-realm/write.html>`__ +method. Within this callback, you are +free to create, read, update, and delete on the realm. + +A realm allows only one open write transaction at a time. Realm +blocks other writes on other threads until the open +transaction is complete. Consequently, there is no race +condition when reading values from the realm within a +transaction. + +When you are done with your transaction, Realm either +commits it or cancels it: + +- When Realm commits a transaction, Realm writes + all changes to disk. For synced realms, the SDK queues the change + for synchronization with the backend. +- When Realm cancels a write transaction or an operation in + the transaction causes an error, all changes are discarded + (or "rolled back"). + +.. note:: Frozen Objects + + Objects returned from a write closure become frozen objects when the + write transaction completes. For more information, refer to + :ref:``. + +.. _kotlin-managed-vs-unmanaged-objects: + +Managed vs. Unmanaged Objects +----------------------------- + +Realm APIs may refer to objects as managed or unmanaged. When you create +a Realm object with the Kotlin SDK, it is unmanaged by the realm. +You can create managed instance by copying an unmanaged object to a realm. +To create an unmanaged copy of a managed object, refer to the +:ref:`` section. + +- **Managed objects** are Realm objects that persist in a realm. Managed objects + can only be accessed from an open realm. They can be automatically updated + with changes within write transactions as long as that realm remains open. + Managed objects are tied to the realm instance from which they originated + and cannot be written to another realm. + + You can use Realm APIs with managed objects, create relationships with + other objects, and observe managed Realm objects for changes. + +- **Unmanaged objects** are instances of Realm objects that + behave like normal Kotlin objects, but they are not persisted in a realm. + All Realm objects are unmanaged until you write them to a realm. + You cannot use Realm APIs with unmanaged objects or observe them for changes. - You can only insert new objects into a realm within a - :ref:`write transaction `. +.. tip:: + + You can check if an object is managed with the + `isManaged() <{+kotlin-local-prefix+}io.realm.kotlin.ext/is-managed.html>`__ + method. + + +Create a New Managed Object +--------------------------- + +After you :ref:`` in your object model +and include it in your realm schema when you open the realm, +you can reference and write those objects in your realm. -Create an Object ----------------- +.. important:: Object Types Must Be in Your Schema -Instantiate Realm objects as you would any other object. In a -transaction, you can add the object to the realm if the -realm's schema includes the object -type. When you add an instance to the realm, it becomes -*managed* by that realm. + You can only write objects whose object type + is included in the realm schema. If you try to + reference or write an object of an object type + that isn't in your schema, Realm will return a + schema validation error. -To persist a new object to a realm: +To persist a new managed object to a realm: 1. Instantiate a new object instance with the class constructor. You can use an `apply block @@ -34,72 +127,287 @@ To persist a new object to a realm: #. Open a write transaction with `realm.write() <{+kotlin-local-prefix+}io.realm.kotlin/-realm/write.html>`__ or `realm.writeBlocking() - <{+kotlin-local-prefix+}io.realm.kotlin/-realm/write-blocking.html>`__. + <{+kotlin-local-prefix+}io.realm.kotlin/-realm/write-blocking.html>`__ + to instantiate the unmanaged object. #. Pass the new object instance to `copyToRealm() <{+kotlin-local-prefix+}io.realm.kotlin/-mutable-realm/copy-to-realm.html>`__ to persist the object data to the realm. This method returns a - *managed* instance of the object. You can modify the persisted - object through the returned instance. + live managed instance of the object. + + .. important:: Asymmetric Objects Use Insert() + + Asymmetric objects are special write-only objects that do not + persist to the realm. They *do not* use ``copyToRealm()``. + Instead, you pass the asymmetric object instance to the + ``insert()`` extension method within a write transaction. + Refer to the :ref:`` section + for more information. + +#. Work with the persisted Realm object + through the returned instance. The live object is accessible until the + write transaction completes. This does not apply to asymmetric objects, + which are write-only and do not persist to the realm. + +You can also upsert into a realm using specific criteria. For more +information, refer to :ref:``. + +Create a Realm Object +~~~~~~~~~~~~~~~~~~~~~ + +To create a new ``RealmObject`` instance, instantiate a new object of a +:ref:`realm object type `. + +In the following example, we instantiate a ``Frog`` object in a +``realm.write()`` block, then pass the instantiated object to +``copyToRealm()`` to return a managed instance: -.. literalinclude:: /examples/generated/kotlin/CRUDTest.snippet.create-a-new-object.kt +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-new-realm-object.kt :language: kotlin -.. tip:: +.. _kotlin-create-an-embedded-object: - You can also upsert into a realm using specific criteria. See - :ref:`Upsert a Realm Object `. +Create an Embedded Object +~~~~~~~~~~~~~~~~~~~~~~~~~ -.. _kotlin-create-a-collection: +To create a new ``EmbeddedRealmObject`` instance, assign an +instance of an :ref:`embedded object type ` to a +parent object's property. This can be in a one-to-one, one-to-many, or +inverse :ref:`relationship ` +depending on how you defined the embedded object within the parent +object type. For more information, refer to +:ref:``. + +.. note:: Embedded Objects Must Be Created Within a Parent Object + + An embedded object requires a parent object and *cannot* exist as an + independent Realm object. + +Embedded objects have strict ownership with their parent object. +After you create the embedded object, you *cannot* reassign it to a +different parent object or share it between multiple parent objects. -Create a Collection -------------------- +In the following example, we instantiate a new ``Contact`` object with an embedded ``Address``, which contains a ``Contact`` object and an embedded +``Country`` object: -You can create collections of items using -``RealmList``, ``RealmSet``, and ``RealmDictionary`` types. +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-one-embedded-object.kt + :language: kotlin -You can also register a notification handler to listen for changes to a -collection. For more information, see -:ref:`React To Changes `. +We also instantiate a new ``Business`` object with a +list of embedded ``Address`` objects, which also contain ``Contact`` +objects and embedded ``Country`` objects: -Create an Object with a RealmSet Property -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-many-embedded-objects.kt + :language: kotlin + :emphasize-lines: 15 -You can create objects that contain :ref:`RealmSet ` -properties as you would any Realm object, but you can only set -the values of a mutable set property within a write transaction. +.. _kotlin-create-asymmetric-object: -For more information about defining a set property, refer to -:ref:`kotlin-define-realm-set-type`. +Create an Asymmetric Object +~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Add Items to a RealmSet -``````````````````````` +.. versionadded:: 1.10.0 -To add a single item to a ``RealmSet``, pass the object you want to add to the set to the -`set.add() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-set/index.html#-153241610%2FFunctions%2F-1651551339>`__ -method: +Unlike other Realm objects, you *do not* +use the ``copyToRealm()`` method to create it. This is because +asymmetric objects are write-only: they are not persisted to the realm. +Instead, you use a special ``insert()`` extension method to insert +it into the realm. -.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-realm-set.kt +To create a new ``AsymmetricRealmObject`` instance, instantiate a +new object of an +:ref:`asymmetric object type ` using +`insert() <{+kotlin-sync-prefix+}io.realm.kotlin.mongodb.ext/insert.html>`__. + +In the following example, we instantiate a new ``WeatherSensor`` +object and pass it to ``insert()`` within a write transaction: + +.. literalinclude:: /examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt :language: kotlin + :emphasize-lines: 10 + +Once inserted, the asymmetric object syncs to the App Services backend +and the linked Atlas database. You *cannot* access the managed data +locally, add it to or remove it from a realm, or query for it. +For information on how to use asymmetric objects in your application, +refer to :ref:`kotlin-stream-data-to-atlas`. + +Create Realm Properties +----------------------- + +Depending on how you define your object type, you might have properties +that are special +:ref:`Realm-specific types `. -To add multiple items to a ``RealmSet``, pass the elements you want -to add to the `set.addAll() -<{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-set/index.html#-800009087%2FFunctions%2F-1651551339>`__ -method: +In the following example, we have a ``Frog`` object type with +several Realm properties: -.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.add-all-to-realm-set.kt +.. literalinclude:: /examples/generated/kotlin/Schema.snippet.create-realm-properties.kt :language: kotlin -Create an Object with a Dictionary Property +Create a RealmInstant (Timestamp) Property +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create a new object instance with a +`RealmInstant +<{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-instant/index.html>`__ +property, instantiate an object and pass an initial value to the +``RealmInstant`` property using either: + +- `RealmInstant.from() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-instant/-companion/from.html>`__: + the epochSeconds and nanoseconds since the Unix epoch +- `RealmInstant.now() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-instant/-companion/now.html>`__: + the epochSeconds and nanoseconds since the Unix epoch until now + +For more information about the ``RealmInstant`` type, refer to +:ref:``. + +In the following example, we instantiate a new ``Frog`` object with a +``birthdate`` property and pass an initial value to ``RealmInstant.from()``: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-realminstant-property.kt + :language: kotlin + +.. _kotlin-create-mutablerealmint: + +Create a MutableRealmInt (Counter) Property ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can create objects with -`RealmDictionary <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-dictionary/index.html>`__ -properties. The ``RealmDictionary`` keys may only be strings, but values may be -any type of Realm-supported primitive, a ``RealmObject``, or an ``EmbeddedObject``. +To create a new object instance with a +`MutableRealmInt +<{+kotlin-local-prefix+}io.realm.kotlin.types/-mutable-realm-int/index.html>`__ +property, instantiate an object and pass an initial value to the +``MutableRealmInt`` property using +`MutableRealmInt.create() <{+kotlin-local-prefix+}io.realm.kotlin.types/-mutable-realm-int/-companion/create.html>`__. +For more information about the ``MutableRealmInt`` type, refer to +:ref:``. + +In the following example, we instantiate a new ``Frog`` object with a +``fliesEaten`` property and pass an initial value to +``MutableRealmInt.create()``: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-mutablerealm-property.kt + :language: kotlin + +.. To learn how to increment, decrement, and set the counter value after +.. you create the object, refer to :ref:``. + +Create a RealmAny (Mixed) Property +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create a new object instance with a polymorphic +`RealmAny <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-any/index.html>`__ +property, instantiate an object and pass an initial value of a +supported type to the ``RealmAny`` property using +`RealmAny.create() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-any/-companion/create.html>`__. +For a list of the value types that ``RealmAny`` can hold, refer to +:ref:``. + +In the following example, we instantiate a new ``Frog`` object with a +``favoriteFood`` list of ``RealmAny`` type and pass the initial values to +``RealmAny.create()``: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-realmany-property.kt + :language: kotlin -For more information about defining a dictionary property, refer to -:ref:`kotlin-define-realm-dictionary-type`. +After you create the object, you can *must* know the stored value type +to work with the ``RealmAny`` property. + +.. To learn how to work with ``RealmAny`` properties after +.. you create the object, refer to :ref:``. + +.. _kotlin-create-a-collection: + +Create Collection Properties +---------------------------- + +Depending on how you define your object type, you might have properties +that are defined as one of the following +supported :ref:``: +``RealmList``, ``RealmSet``, and ``RealmDictionary``. For more information, +refer to :ref:``. + +Collections are mutable: you can add and remove elements in a collection +within a write transaction. + +Collections can contain both managed and unmanaged objects. When a +you copy a collection to the realm, you create a managed instance of the +collection *and* all elements in the collection, including any +unmanaged elements. Unmanaged collections behave like their corresponding +Kotlin classes and are not persisted to the realm. + +.. tip:: Listen for Changes to a Created Collection + + After you create a collection, you can register a notification handler to listen for changes. For more information, refer to :ref:``. + +Create a RealmList +~~~~~~~~~~~~~~~~~~ + +To create a new object instance with a +`RealmList <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-list/index.html>`__ +property, instantiate an object and pass any values of a +supported type to the ``RealmList`` property. For a list of the value types +that ``RealmList`` can hold, refer to :ref:``. + +You can instantiate an unmanaged list with `realmListOf() <{+kotlin-local-prefix+}io.realm.kotlin.ext/realm-list-of.html>`__ +or pass elements to the list using +`list.add() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-list/index.html#882550416%2FFunctions%2F878332154>`__, +`list.addAll() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-list/index.html#-4875109%2FFunctions%2F878332154>`__, +or `list.set() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-list/set.html>`__. +The list is unmanaged until you copy it to the realm. + +In the following example, we instantiate a new ``Frog`` object with +initial values for several ``RealmList`` properties: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-realm-list.kt + :language: kotlin + +Create a RealmSet Property +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create a new object instance with a +`RealmSet +<{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-set/index.html>`__ +property, instantiate an object and pass any values of a +supported type to the ``RealmSet`` property. For a list of valid value types +that ``RealmSet`` can hold, refer to :ref:``. + +You can instantiate an unmanaged set with `realmSetOf() <{+kotlin-local-prefix+}io.realm.kotlin.ext/realm-list-of.html>`__ +or pass elements to the set using +`set.add() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-set/index.html#-153241610%2FFunctions%2F878332154>`__ +or +`set.addAll() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-set/index.html#-800009087%2FFunctions%2F878332154>`__. +The set is unmanaged until you copy it to the realm. + +In the following example, we instantiate a new ``Frog`` object with +initial values for ``favoriteSnacks`` and ``favoriteWeather`` set +properties: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-realm-set.kt + :language: kotlin + +Create a Dictionary Property +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create a new object instance with a +`RealmDictionary <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-dictionary/index.html>`__ +property, instantiate an object and pass any key-value pairs of a +supported type to the ``RealmDictionary`` property. +``RealmDictionary`` only accepts a ``String`` key, but values may be +non-string types. For a list of valid value types, refer to +:ref:``. + +You can instantiate an unmanaged dictionary with +`realmDictionaryOf() <{+kotlin-local-prefix+}io.realm.kotlin.ext/realm-dictionary-of.html>`__ or +`realmDictionaryEntryOf() <{+kotlin-local-prefix+}io.realm.kotlin.ext/realm-dictionary-entry-of.html>`__. +Or you can pass key-values using +`put() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-dictionary/index.html#1052690691%2FFunctions%2F878332154>`__ +or +`putAll() <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-dictionary/index.html#-704210467%2FFunctions%2F878332154>`__. +The dictionary is unmanaged until you copy it to the realm. + +In the following example, we instantiate a new ``Frog`` object with +initial key-values for several dictionary properties: .. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-dictionary.kt :language: kotlin @@ -109,38 +417,94 @@ For more information about defining a dictionary property, refer to .. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.percent-encode-disallowed-characters.kt :language: kotlin -Create an Embedded Object -------------------------- +Create a Relationship +--------------------- -To create an :ref:`embedded object `, assign an -instance of the -`EmbeddedRealmObject <{+kotlin-local-prefix+}io.realm.kotlin.types/-embedded-realm-object/index.html>`__ -to a parent object's property: +Depending on how you define your object type, you might have properties +that reference another Realm object. This can be a to-one, to-many, or +inverse :ref:`relationship `. +For more information on defining relationships in your object model, +refer to :ref:``. -.. literalinclude:: /examples/generated/kotlin/DataTypesTest.snippet.create-embedded-object.kt - :language: kotlin +You can also embed one Realm object directly within another to create +a nested data structure with an ``EmbeddedRealmObject`` type. +To create a relationship with an embedded object, refer to the +:ref:`` section. -.. _kotlin-create-asymmetric-object: +Create a To-One Relationship +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Create an Asymmetric Object ---------------------------- +To create a new object instance with a +:ref:`to-one relationship ` +property, instantiate both objects and pass the referenced object in the +relationship property. -.. versionadded:: 1.10.0 +In the following example, we instantiate a new ``Frog`` object with a +``favoritePond`` property that references a ``Pond`` object and a +``bestFriend`` property that references another ``Frog`` object: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-to-one-realm-relationship.kt + :language: kotlin -An asymmetric object is an insert-only object. -When you create an ``AsymmetricRealmObject``, it syncs unidirectionally via -:ref:`Data Ingest ` to the Atlas -database linked to your Atlas App Services App. You cannot access an -``AsymmetricRealmObject`` locally, add it to or remove it from a realm, or query for it. -For more information, see :ref:`Asymmetric Objects `. +Create a To-Many Relationship +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You must create an `AsymmetricRealmObject <{+kotlin-sync-prefix+}io.realm.kotlin.types/-asymmetric-realm-object/index.html>`__ -using the `insert() <{+kotlin-sync-prefix+}io.realm.kotlin.mongodb.ext/insert.html>`__ -extension method within a write transaction: +To create a new object instance with a +:ref:`to-many relationship ` +property, instantiate all objects and pass any referenced objects in the +relationship collection property. -.. literalinclude:: /examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt +In the following example, we instantiate a new ``Forest`` object with a +``frogsThatLiveHere`` property that references a set of ``Frog`` +objects and a ``nearBy`` property that references a list of +``Pond`` objects: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-to-many-realm-relationship.kt :language: kotlin -You can create asymmetric objects for a realm initialized with a Flexible Sync -`SyncConfiguration <{+kotlin-sync-prefix+}io.realm.kotlin.mongodb.sync/-sync-configuration/index.html>`__. -For more information, see :ref:`Open the synced Realm with a Flexible Sync configuration `. +Create an Inverse Relationship +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create a new object instance with an +:ref:`inverse relationship ` +property, instantiate the parent object and pass any referenced child +objects in the backlink collection property. + +In the following example, we instantiate a new ``User`` object with a +backlinks ``posts`` property that references a list of ``Post`` objects: + +.. literalinclude:: /examples/generated/kotlin/CreateTest.snippet.create-inverse-realm-relationship.kt + :language: kotlin + +After you create the object, you can access the backlinks collection +property to get the child objects. You *cannot* directly modify +the backlink itself. + +.. For more information, refer to :ref:``. + +.. _kotlin-create-unmanaged-copy: + +Create an Unmanaged Copy of a RealmObject or Collection +------------------------------------------------------- + +You can create an unmanaged copy of a managed object or collection +by passing it to +`copyFromRealm() <{+kotlin-local-prefix+}io.realm.kotlin.ext/copy-from-realm.html>`__. +This method returns an unmanaged, in-memory +copy of the object or collection. For collections, this is a deep copy +that includes all referenced objects up to the specified ``depth``. + +In the following example, we create an unmanaged copy of an existing +managed ``Pond`` object that contains a list of two ``Frog`` objects. +After copying the object from the realm, we confirm that the copy is +unmanaged and contains both referenced ``Frog`` objects: + +.. io-code-block:: + + .. input:: /examples/generated/kotlin/CreateTest.snippet.create-unmanaged-copy.kt + :language: kotlin + + .. output:: + + Unmanaged pond name: Big Pond + Unmanaged frogs: Kermit, Froggy Jay diff --git a/source/sdk/kotlin/realm-database/schemas/define-realm-object-model.txt b/source/sdk/kotlin/realm-database/schemas/define-realm-object-model.txt index 81bd551e97..ec21a64855 100644 --- a/source/sdk/kotlin/realm-database/schemas/define-realm-object-model.txt +++ b/source/sdk/kotlin/realm-database/schemas/define-realm-object-model.txt @@ -106,6 +106,8 @@ classes to the realm's configuration when you :ref:`open a realm constructor(): this("", 0) // Empty constructor required by Realm } +.. _kotlin-define-realm-object-type: + Define a Realm Object Type ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -180,8 +182,7 @@ Data Ingest with your application, refer to :ref:`kotlin-stream-data-to-atlas`. .. include:: /includes/kotlin-asymmetric-object.rst -To define an :ref:`asymmetric object type`, create a -Kotlin class that implements the `AsymmetricRealmObject +To define an asymmetric object type, create a Kotlin class that implements the `AsymmetricRealmObject <{+kotlin-sync-prefix+}io.realm.kotlin.types/-asymmetric-realm-object/index.html>`__ interface: @@ -197,7 +198,7 @@ A collection is an object that contains zero or more instances of a supported data type. Realm collections are homogenous (all objects in a collection are of the same type) and are backed by their corresponding built-in Kotlin classes. For more information on the collection types used in the Kotlin SDK and their -supported data types, refer to :ref:`Collection Types `. +supported data types, refer to :ref:``. The Kotlin SDK offers several collection types that you can use as properties in your data model: ``RealmList``, ``RealmSet``, and diff --git a/source/sdk/kotlin/realm-database/schemas/relationships.txt b/source/sdk/kotlin/realm-database/schemas/relationships.txt index 5e517b1743..990ffead7e 100644 --- a/source/sdk/kotlin/realm-database/schemas/relationships.txt +++ b/source/sdk/kotlin/realm-database/schemas/relationships.txt @@ -36,6 +36,8 @@ relationship to "one to one/one to many" instead of "many to one/many to many" is to use an :ref:`embedded object `, which is a nested object with exactly one parent. +.. _kotlin-define-a-relationship: + Define a Relationship --------------------- diff --git a/source/sdk/kotlin/realm-database/schemas/supported-types.txt b/source/sdk/kotlin/realm-database/schemas/supported-types.txt index 5a271c0dff..07bc9bae9d 100644 --- a/source/sdk/kotlin/realm-database/schemas/supported-types.txt +++ b/source/sdk/kotlin/realm-database/schemas/supported-types.txt @@ -297,6 +297,8 @@ Additionally, ``MutableRealmInt`` fields: they create a new, unmanaged ``MutableRealmInt`` instance with the updated value. +Learn how to :ref:``. + .. _kotlin-timestamps: RealmInstant (Timestamp) @@ -363,20 +365,14 @@ that contains zero or more instances of one supported data type. Realm collections are homogenous (all objects in a collection are of the same type) and are backed by their corresponding built-in Kotlin classes. -User-created collections are unmanaged until they are copied to the realm -and can contain both managed and unmanaged objects. Unmanaged collections -behave like their corresponding Kotlin classes and are not persisted to the realm. -Refer to :ref:`Managed vs. Unmanaged Objects ` -for more information. - Collection types are non-null. When you define a collection property, you must initialize it. -Learn how to :ref:`Create a Collection `. +For more information, refer to :ref:`Create a Collection `. .. _kotlin-realm-list: -RealmLists -~~~~~~~~~~ +RealmList +~~~~~~~~~ The `RealmList <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-list/index.html>`__ type implements Kotlin's @@ -403,8 +399,8 @@ containing: .. _kotlin-realm-set: -RealmSets -~~~~~~~~~ +RealmSet +~~~~~~~~ The `RealmSet <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-set/index.html>`__ @@ -431,8 +427,8 @@ You cannot use ``EmbeddedRealmObject`` elements in a ``RealmSet``. .. _kotlin-realm-dictionary: -RealmMap/RealmDictionaries -~~~~~~~~~~~~~~~~~~~~~~~~~~ +RealmMap/RealmDictionary +~~~~~~~~~~~~~~~~~~~~~~~~ The `RealmMap <{+kotlin-local-prefix+}io.realm.kotlin.types/-realm-map/index.html>`__ type implements Kotlin's `Map diff --git a/source/sdk/kotlin/realm-database/write-transactions.txt b/source/sdk/kotlin/realm-database/write-transactions.txt deleted file mode 100644 index 695cdac0f9..0000000000 --- a/source/sdk/kotlin/realm-database/write-transactions.txt +++ /dev/null @@ -1,137 +0,0 @@ -.. _kotlin-read-write-data: - -============================== -Read & Write Data - Kotlin SDK -============================== - -.. toctree:: - :titlesonly: - - Create - Read - Update - Delete - -.. contents:: On this page - :local: - :backlinks: none - :depth: 2 - :class: singlecol - -Realm uses a highly efficient storage engine -to persist objects. You can: - -- :ref:`create realm objects `, -- :ref:`read realm objects `, -- :ref:`update realm objects `, -- and eventually :ref:`delete objects from a realm `. - -.. _kotlin-write-transactions: - -Write Transactions ------------------- - -Because the create, update, and delete operations modify the state of -the realm, we call them writes. - -Realm handles writes in terms of **transactions**. A -transaction is a list of read and write operations that -Realm treats as a single indivisible operation. In other -words, a transaction is *all or nothing*: either all of the -operations in the transaction succeed or none of the -operations in the transaction take effect. - -.. note:: - - All writes must happen in a transaction. - -A realm allows only one open write transaction at a time. Realm -blocks other writes on other threads until the open -transaction is complete. Consequently, there is no race -condition when reading values from the realm within a -transaction. - -When you are done with your transaction, Realm either -commits it or cancels it: - -- When Realm **commits** a transaction, Realm writes - all changes to disk. For synced realms, the SDK queues the change - for synchronization with the backend. -- When Realm **cancels** a write transaction or an operation in - the transaction causes an error, all changes are discarded - (or "rolled back"). - -.. _kotlin-managed-vs-unmanaged-objects: - -Managed vs. Unmanaged Objects ------------------------------ - -Realm APIs may refer to objects as managed or unmanaged. When you create -a Realm object, it is unmanaged. You can then create a managed instance by -copying that object to a realm. - -You can check if an object is managed with the -`isManaged() <{+kotlin-local-prefix+}io.realm.kotlin.ext/is-managed.html>`__ -method. - -Managed Objects -~~~~~~~~~~~~~~~ - -**Managed objects** are Realm objects that persist in a realm. Managed objects -can only be accessed from an open realm. They can be automatically updated -with changes within write transactions as long as that realm remains open. -Managed objects are tied to the realm instance from which it originated -and cannot be written to another realm. - -You can use Realm APIs with managed objects, create relationships with -other objects, and observe managed Realm object for changes. - -You create managed objects by copying unmanaged instances to a realm with -`Realm.copyToRealm() <{+kotlin-local-prefix+}io.realm.kotlin.dynamic/-dynamic-mutable-realm/copy-to-realm.html>`__. -See :ref:`Create Realm Objects ` for more -information. - -.. note:: - - You can :ref:`create managed asymmetric objects `. - But because asymmetric objects are write-only, it isn't possible to - access the managed data after it has been written. - -Unmanaged Objects -~~~~~~~~~~~~~~~~~ - -**Unmanaged objects** are instances of Realm objects that -behave like normal Kotlin objects, but they are not persisted in a realm. -All Realm objects are unmanaged until you write them to a realm. -You cannot use Realm APIs with unmanaged objects or observe them for changes. - -You can create an unmanaged object by manually constructing a Realm object -yourself or by copying a managed object with -`Realm.copyFromRealm() <{+kotlin-local-prefix+}io.realm.kotlin.ext/copy-from-realm.html>`__. - -.. _kotlin-open-a-transaction: - -Run a Transaction ------------------ - -Realm represents each transaction as a callback function -that contains zero or more read and write operations. To run -a transaction, define a transaction callback and pass it to -the realm's ``write`` method. Within this callback, you are -free to create, read, update, and delete on the realm. If -the code in the callback throws an exception when Realm runs -it, Realm cancels the transaction. Otherwise, Realm commits -the transaction immediately after the callback. - -.. example:: - - The following code shows how to run a transaction with - `write() <{+kotlin-local-prefix+}io.realm.kotlin/-realm/write.html>`__ - or `writeBlocking() <{+kotlin-local-prefix+}io.realm.kotlin/-realm/write-blocking.html>`__. - If the code in the callback throws an exception, Realm - cancels the transaction. Otherwise, Realm commits the - transaction. - - .. literalinclude:: /examples/generated/kotlin/CRUDTest.snippet.run-a-transaction.kt - :language: kotlin -