============================== Declaring models ============================== Model declaration ----------------------- The cql :ref:`model ` declaration is based on the GORM model declaration, so its definition, conventions, tags and associations are compatible with cql. For details see `gorm documentation `_. On the contrary, cql presents some differences/extras that are explained in this section. Base models ----------------------- To be considered a model, your structures must have embedded one of the :ref:`base models ` provided by cql: Simple models: - `model.UUIDModel`: Model identified by a model.UUID (Random (Version 4) UUID). - `model.UIntModel`: Model identified by a model.UIntID (auto-incremental uint). Models with timestamps: These base models also provide date created, updated and :ref:`deleted `. - `model.UUIDModelWithTimestamps`: Model identified by a model.UUID (Random (Version 4) UUID). - `model.UIntModelWithTimestamps`: Model identified by a model.UIntID (auto-incremental uint). To use them, simply embed the desired model in any of your structs: .. code-block:: go type MyModel struct { model.UUIDModel Name string Email *string Age uint8 Birthday *time.Time MemberNumber sql.NullString ActivatedAt sql.NullTime // ... } Type of attributes ----------------------- As we can see in the example in the previous section, the attributes of your models can be of multiple types, such as basic go types, pointers, and :ref:`nullable types `. This difference can generate differences in the data that is stored in the database, since saving a model created as follows: .. code-block:: go MyModel{} will save a empty string for Name but a NULL for the Email and the MemberNumber. The use of nullable types is strongly recommended and cql takes into account their use in each of its functionalities. Associations ----------------------- All associations provided by GORM are supported. For more information see , , and . However, in this section we will give some differences in cql and details that are not clear in this documentation. IDs ^^^^^^^^^^^^^^^^^^^^^ Since cql base models use model.UUID or model.UIntID to identify the models, the type of id used in a reference to another model is the corresponding one of these two, for example: .. code-block:: go type ModelWithUUID struct { model.UUIDModel } type ModelWithUIntID struct { model.UIntModel } type ModelWithReferences struct { model.UUIDModel ModelWithUUID *ModelWithUUID ModelWithUUIDID *model.UUID ModelWithUIntID *ModelWithUIntID ModelWithUIntIDID *model.UIntID } References ^^^^^^^^^^^^^^^^^^^^^ References to other models can be made with or without pointers: .. code-block:: go type ReferencedModel struct { model.UUIDModel } type ModelWithPointer struct { model.UUIDModel // reference with pointer PointerReference *ReferencedModel PointerReferenceID *model.UUID } type ModelWithoutPointer struct { model.UUIDModel // reference without pointer Reference ReferencedModel ReferenceID model.UUID } As in the case of attributes, this can make a difference when persisting, since one created as follows: .. code-block:: go ModelWithoutPointer{} will also create and save an empty ReferencedModel{}, what may be undesired behavior. For this reason, although both options are still compatible with cql, we recommend the use of pointers for references. In case the relation is not nullable, use the `not null` tag in the id of the reference, for example: .. code-block:: go type ReferencedModel struct { model.UUIDModel } type ModelWithPointer struct { model.UUIDModel // reference with pointer not null PointerReference *ReferencedModel PointerReferenceID *model.UUID `gorm:"not null"` } Reverse reference ------------------------------------ Although no example within the `gorm's documentation `_ shows it, when defining relations, we can also put a reference in the reverse direction to add navigability to our model. In addition, adding this reverse reference will allow the corresponding conditions to be generated during condition generation. For example: .. code-block:: go type Related struct { model.UUIDModel YourModel *YourModel } type YourModel struct { model.UUIDModel Related *Related RelatedID *model.UUID }