Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(DOCSP-39502): Consolidate Define an Object Model page #3314

Merged
merged 36 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
633153b
Draft concept content and stage for discussion
dacharyc Jun 27, 2024
ea2523f
Tweak wording and fix wrong include path
dacharyc Jun 27, 2024
e4c6a72
Add CSharp object model and schema information
dacharyc Jun 28, 2024
cd41763
Add Dart object model and schema information
dacharyc Jun 28, 2024
43e9170
Update Dart include paths
dacharyc Jun 28, 2024
3ef2481
Add Java SDK object model and schema information
dacharyc Jun 28, 2024
8446600
Add (incomplete) JS and TS object model and schema information
dacharyc Jun 28, 2024
2eefb50
Add Kotlin object model and schema information
dacharyc Jun 28, 2024
7102a45
Add Swift and Objective-C object model and schema information
dacharyc Jun 29, 2024
507f079
Remove headings from includes to avoid headings in OTP
dacharyc Jun 29, 2024
5c5fe67
Bold the object model for consistency in intro content
dacharyc Jun 29, 2024
937dd9a
Add indexed property
dacharyc Jul 9, 2024
927b3c5
Add FTS details
dacharyc Jul 9, 2024
36dac9c
Add info about primary keys
dacharyc Jul 9, 2024
3ade84c
Update the MissingPlaceholders to literalincludes you can't copy
dacharyc Jul 9, 2024
3d493ad
Try to fix snooty build error
dacharyc Jul 9, 2024
f3090eb
Make missing placeholders not copyable
dacharyc Jul 9, 2024
e37070f
Add optional property details
dacharyc Jul 9, 2024
aa13a8a
Add ignored property details
dacharyc Jul 9, 2024
7b8c8c1
Fix snooty build error
dacharyc Jul 9, 2024
a2f7ed2
Add details about default values
dacharyc Jul 9, 2024
d33584d
Add info about unstructured data
dacharyc Jul 9, 2024
6610a2d
Fix dart include file path
dacharyc Jul 9, 2024
cb69ad8
Rename supported property types to define property types to mirror Cr…
dacharyc Jul 9, 2024
838e855
Fix title underline too short warnings
dacharyc Jul 9, 2024
3474c26
Add details about mapping a model or property name to different store…
dacharyc Jul 10, 2024
2c93197
Minor cleanup
dacharyc Jul 10, 2024
ac55416
Add information about projection
dacharyc Jul 10, 2024
e7cf6f8
Add info about custom setters
dacharyc Jul 10, 2024
6fee88c
Incorporate feedback about creating objects for JS/TS
dacharyc Jul 10, 2024
2eb6793
Rename includes to comply with naming conventions
dacharyc Jul 10, 2024
eb979a7
Add missing Swift model to the projection description
dacharyc Jul 10, 2024
ddf4b99
Update the metadata information
dacharyc Jul 10, 2024
1742ab1
Incorporate additional info about indexes from related Jira ticket
dacharyc Jul 10, 2024
9a1956f
Add JS and TS descriptions for defining SDK and Realm models
dacharyc Jul 17, 2024
1e30fb0
Incorporate review feedback
dacharyc Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1 @@
part 'schemas.realm.dart';
part 'modelFile.realm.dart';
4 changes: 2 additions & 2 deletions source/frameworks/flutter/quick-start.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ classes in your application code with an SDK object schema.
You then have to generate the :flutter-sdk:`RealmObjectBase <realm/RealmObjectBase-mixin.html>`
class that's used within your application.

For more information, refer to :ref:`Define an Object Schema
<sdks-define-object-schema>`.
For more information, refer to :ref:`Define an Object Model
<sdks-define-objects>`.

.. procedure::

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In C++, when opening a database, you must specify which models are available by
passing the models to the template you use to open the database. Those
models must have schemas, and this list of schemas becomes the database schema.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
In C++, define an asymmetric object the same way you would
a regular C++ struct or class. Provide a ``REALM_ASYMMETRIC_SCHEMA`` with the
struct or class name as the first argument. Add the names of any properties
that you want the database to persist.

An ``asymmetric_object`` broadly has the same :ref:`supported types
<sdks-define-property-types>` as ``realm::object``, with a few exceptions:

- Asymmetric objects can link to the following types:
- ``object``
- ``embedded_object``
- ``std::vector<embedded_object>``
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
In C++, you define an embedded object by providing a ``REALM_EMBEDDED_SCHEMA``
whose first argument is the struct or class name. Add the names of any
properties that you want the database to persist.

Define a property as an embedded object on the parent object by setting
a pointer to the embedded object's type.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The C++ SDK does not currently support geospatial data.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
In C++, define an optional type using the class template
`std::optional <https://en.cppreference.com/w/cpp/utility/optional>`__.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
In C++, the base :cpp-sdk:`object <structrealm_1_1internal_1_1bridge_1_1object.html>`
provides accessors and other methods to work with SDK objects, including
things like:

- Checking whether an object is valid
- Getting its managing database instance
- Registering a notification token

Define a C++ struct or class as you would normally. Add a ``REALM_SCHEMA``
whose first value is the name of the struct or class. Add the names of the
properties that you want the database to manage. Omit any fields that you do
not want to persist.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
In the C++ SDK, you can define your models as regular C++ structs or classes.
Provide an :ref:`sdks-object-schema` with the object type name and
the names of any properties that you want to persist to the database. When you
add the object to the database, the SDK ignores any properties that you omit
from the schema.

You must declare your object and the schema within the ``realm`` namespace.
You must then use the ``realm`` namespace when you initialize and perform CRUD
operations with the object.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
C++ supports primary keys of the following types, and their optional variants:

- ``int64_t``
- ``realm::object_id``
- ``realm::uuid``
- ``std::string``

Additionally, a required ``realm::enum`` property can be a primary key, but
``realm::enum`` cannot be optional if it is used as a primary key.

Set a property as a primary key with the ``primary_key`` template.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The C++ SDK does not currently support Full-Text Search.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
To ignore a property, omit it from the :ref:`object schema <sdks-object-schema>`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The C++ SDK does not currently support indexing a property.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
C++ does not currently provide an API to map a model or property name to a
different stored name.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
The C++ SDK object model is a regular C++ class or struct that contains
a collection of properties. When you define your C++ class or struct, you
must also provide an object schema. The schema is a C++ macro that gives the
SDK information about which properties to persist, and what type of database
object it is.

You must define your SDK object model within the ``realm`` namespace.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
In C++, schemas are managed through macros. The schema must list every
property type that you want to persist. The SDK inspects the object model to
determine the property types and other special information, such as whether
a property is the object's primary key.

A schema must accompany every object model you want to persist, and it may be
one of:

- ``REALM_SCHEMA``
- ``REALM_EMBEDDED_SCHEMA``
- ``REALM_ASYMMETRIC_SCHEMA``

You must define the schema and your object model within the ``realm`` namespace.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
C++ does not currently support modeling unstructured data as a collection
of the mixed property type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
In C#, you can define object schemas by using the C# class declarations.
When a database is initialized, it discovers the SDK objects defined in all
assemblies that have been loaded and generates schemas accordingly. If you
want to restrict a database to manage only a subset of the SDK models in the
loaded assemblies, you *can* explicitly pass the models when configuring a
database.

For more information, refer to :ref:`sdks-provide-a-subset-of-models-to-a-database`.

.. note::

.NET does not load an assembly until you reference a class in it. If you
define your object models in one assembly and instantiate a database
in another, be sure to call a method in the assembly that contains the object
models *before* initialization. Otherwise, the SDK does not discover
the objects when it first loads.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In C#, to define a asymmetric object, inherit from the the
:dotnet-sdk:`IAsymmetricObject <reference/Realms.IAsymmetricObject.html>`
interface and declare the class a ``partial`` class.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
In the following code, the private ``email`` property is stored in the database,
but the public ``Email`` property, which provides validation, is not persisted.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
In C#, to define an embedded object, inherit from the the
:dotnet-sdk:`IEmbeddedObject <reference/Realms.IEmbeddedObject.html>` interface
and declare the class a ``partial`` class. You can reference an embedded object
type from parent object types in the same way as you would define a relationship.

Consider the following example where the ``Address`` is an Embedded Object. Both
the ``Contact`` and the ``Business`` classes reference the ``Address`` as an
embedded object.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
In C#, to create a class that conforms to the GeoJSON spec:

1. Create an embedded object (a class that inherits from
:dotnet-sdk:`IEmbeddedObject <reference/Realms.IEmbeddedObject.html>`).

#. At a minimum, add the two fields required by the GeoJSON spec:

- A field of type ``IList<double>`` that maps to a "coordinates" (case sensitive)
property in the object schema.

- A field of type ``string`` that maps to a "type" property. The value of this
field must be "Point".

The following example shows an embedded class named "CustomGeoPoint" that is used
to persist GeoPoint data:

.. literalinclude:: /examples/generated/dotnet/CustomGeoPoint.snippet.customgeopoint.cs
:language: csharp

Use the Embedded Class
``````````````````````

You then use the custom GeoPoint class in your SDK object model, as shown in
the following example.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
In C#, value types, such as ``int`` and ``bool``, are implicitly non-nullable.
However, they can be made optional by using the question mark (``?``) `notation
<https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types>`__.

Beginning with C# 8.0, nullable reference types were introduced. If your project
is using C# 8.0 or later, you can also declare reference types, such as ``string``
and ``byte[]``, as nullable with ``?``.

.. note::

Beginning with .NET 6.0, the nullable context is enabled by default for new
projects. For older projects, you can manually enable it. For more information,
refer to `<https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-reference-types#setting-the-nullable-context>`__.

The SDK fully supports the nullable-aware context and uses nullability
to determine whether a property is required or optional.

Alternatives to the Nullable-Aware Context
``````````````````````````````````````````

If you are using the older schema type definition (your classes derive from
the ``RealmObject`` base class), or you do not have nullability enabled, you
must use the :dotnet-sdk:`[Required] <reference/Realms.RequiredAttribute.html>`
attribute for any required ``string`` and ``byte[]`` property.

You may prefer to have more flexibility in defining the nullability of properties
in your SDK objects. You can do so by setting ``realm.ignore_objects_nullability = true``
in a `global configuration file <https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files>`__.

If you enable ``realm.ignore_objects_nullability``, the SDK ignores nullability
annotations on object properties, including collections of SDK objects.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
In C#, to define a Realm object, inherit from the the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In C#, to define a Realm object, inherit from the the
In C#, to define an SDK object, inherit from the the

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this case, we are specifically talking about Realm object versus the other object types (Asymmetric, Embedded) so this is an appropriate Realm usage.

:dotnet-sdk:`IRealmObject <reference/Realms.IRealmObject.html>` interface and
declare the class a ``partial`` class.

The following code block shows an object schema that describes a Dog.
Every Dog object must include a ``Name`` and may
optionally include the dog's ``Age``, ``Breed`` and a list of people that
represents the dog's ``Owners``.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
All SDK objects inherit from the
:dotnet-sdk:`IRealmObject <reference/Realms.IRealmObject.html>`,
:dotnet-sdk:`IEmbeddedObject <reference/Realms.IEmbeddedObject.html>`, or
:dotnet-sdk:`IAsymmetricObject <reference/Realms.IAsymmetricObject.html>`
interface and must be declared ``partial`` classes.

In versions of the .NET SDK v10.18.0 and earlier, objects derive from
:dotnet-sdk:`RealmObject <reference/Realms.RealmObject.html>`,
:dotnet-sdk:`EmbeddedObject <reference/Realms.EmbeddedObject.html>`, or
:dotnet-sdk:`AsymmetricObject <reference/Realms.AsymmetricObject.html>`
base classes. This approach to SDK model definition is still supported, but
does not include new features such as the :ref:`nullability annotations
<sdks-optional-property-types>`. These base classes will be
deprecated in a future SDK release. You should use the interfaces for any
new classes that you write and should consider migrating your existing
classes.

.. literalinclude:: /examples/generated/dotnet/ObjectModelsAndSchemas.snippet.dog_class.cs
:language: csharp

**Customize the Object Schema (Optional)**

You can use the
:dotnet-sdk:`Schema <reference/Realms.RealmConfigurationBase.html#Realms_RealmConfigurationBase_Schema>`
property of the
:dotnet-sdk:`RealmConfigurationBase <reference/Realms.RealmConfigurationBase.html>`
object to customize how schemas are defined. The following code example shows
three ways to do this, from easiest to most complex:

- Automatic configuration
- Manual configuration
- A mix of both methods
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
You can create a primary key with any of the following types (or their nullable counterparts):

- ``ObjectId``
- ``UUID``
- ``string``
- ``char``
- ``byte``
- ``short``
- ``int``
- ``long``

To designate a property as the object's primary key, use the
:dotnet-sdk:`Primary Key <reference/Realms.PrimaryKeyAttribute.html>` attribute.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
To index an FTS property, use the :dotnet-sdk:`Indexed <reference/Realms.IndexedAttribute.html>`
attribute with the :dotnet-sdk:`IndexType.FullText <reference/Realms.IndexType.html>`
enum. In the following example, we have a ``FullText`` index on the
``Biography`` property:
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A property is ignored by default if it is not autoimplemented or
does not have a setter.

Ignore an object property with the
:dotnet-sdk:`Ignored <reference/Realms.IgnoredAttribute.html>` attribute.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
You can index properties of these data types:

- ``bool``
- ``byte``
- ``short``
- ``int``
- ``long``
- ``DateTimeOffset``
- ``char``
- ``string``
- ``ObjectId``
- ``UUID``

To index a property, use the :dotnet-sdk:`Indexed <reference/Realms.IndexedAttribute.html>`
attribute. With the ``Indexed`` attribute, you can specify the type of index
on the property by using the :dotnet-sdk:`IndexType <reference/Realms.IndexType.html>`
enum.

In the following example, we have a default ("General") index on the ``Name``
property:
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Use the :dotnet-sdk:`[MapTo] <reference/Realms.MapToAttribute.html>`
attribute to rename a class or property.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Starting in SDK version 12.22.0, you can store collections of mixed data
within a ``RealmValue`` property.

To model unstructured data in your app, define the appropriate properties in
your schema as :ref:`RealmValue <sdks-mixed-data-type>` types. You can then
set these ``RealmValue`` properties as a :ref:`list <sdks-list-property-types>`
or a :ref:`dictionary <sdks-dictionary-property-types>` of ``RealmValue``
elements.

Note that ``RealmValue`` *cannot* represent a set or an embedded object.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
In C#, SDK object models are regular C# classes that define the SDK data model.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
In C#, when the SDK processes SDK object types, it generates a schema for each
class based on the class properties. However, there may be times that you want
to manually define the schema, and the .NET SDK provides a mechanism for doing
so.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
You can use the built-in language features to assign a default value to a property.
In C#, you can assign a default value on primitives in the property declaration.

.. note:: Default Values and Nullability

While default values ensure that a newly created object cannot contain
a value of ``null`` (unless you specify a default value of ``null``),
they do not impact the nullability of a property. For details about
nullability, refer to :ref:`sdks-optional-property-types`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
In Dart, the database configuration takes a :flutter-sdk:`RealmSchema
<realm/RealmSchema-class.html>` that has an iterable collection of
:flutter-sdk:`SchemaObjects <realm/SchemaObject-class.html>`. These
``SchemaObjects`` represent the SDK object types that the database file can
manage.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
In Dart, to define an asymmetric object, create a class model and add the
`RealmModel <https://pub.dev/documentation/realm_common/latest/realm_common/RealmModel-class.html>`__
annotation. Pass `ObjectType.asymmetricObject
<https://pub.dev/documentation/realm_common/latest/realm_common/ObjectType.html>`__
to the ``@RealmModel()`` annotation.

Follow the :ref:`sdks-define-objects` procedure detailed on this
page to generate the ``RealmObject`` model and schema definitions.

Then, use the generated ``RealmObject`` model in your application code.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
In Dart, to define an embedded object, create a class model and add the
`RealmModel <https://pub.dev/documentation/realm_common/latest/realm_common/RealmModel-class.html>`__
annotation. Pass `ObjectType.embeddedObject
<https://pub.dev/documentation/realm_common/latest/realm_common/ObjectType.html>`__
to the ``@RealmModel()`` annotation.

Embedded objects must be nullable when defining them in the parent object's
``RealmModel``. You can use the :flutter-sdk:`parent
<realm/EmbeddedObjectExtension/parent.html>` property to access the parent of
the embedded object.

Follow the :ref:`sdks-define-objects` procedure detailed on this
page to generate the ``RealmObject`` model and schema definitions.

Then, use the generated ``RealmObject`` model in your application code.

The following example shows how to model an embedded object in a Realm object
schema. The ``_Address`` model is embedded within the ``_Person`` model.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
In Dart, to create a class that conforms to the GeoJSON spec, you:

1. Create an embedded object. For more information about embedded
objects, refer to :ref:`sdks-object-models`.

#. At a minimum, add the two fields required by the GeoJSON spec:

- A field of type ``double[]`` that maps to a "coordinates" (case sensitive)
property in the schema.

- A field of type ``string`` that maps to a "type" property. The value of this
field must be "Point".

The following example shows an embedded class named ``MyGeoPoint`` that is
used to persist geospatial data:

.. literalinclude:: /examples/generated/flutter/geospatial_data_test.snippet.define-geopoint-class.dart
:language: dart

Use the Embedded Class
```````````````````````

You then use the custom ``MyGeoPoint`` class in your data model, as shown
in the following example:
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In Dart, value types are implicitly non-nullable, but can be made optional
(nullable) by appending `? <https://dart.dev/null-safety>`__. Include ``?``
to make properties optional.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
In Dart, to define a Realm object, create a class model and add the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In Dart, to define a Realm object, create a class model and add the
In Dart, to define an SDK object, create a class model and add the

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel pretty strongly that we should keep the Realm name for the Realm object type, so I'll skip applying any of these name change suggestions that are specific to Realm objects.

`RealmModel <https://pub.dev/documentation/realm_common/latest/realm_common/RealmModel-class.html>`__
annotation. Follow the :ref:`sdks-define-objects` procedure detailed on this
page to generate the ``RealmObject`` model and schema definitions.

Then, use the generated ``RealmObject`` model in your application code.
Loading
Loading