Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -29,7 +29,7 @@ fields:

This will generate a class with both `name` and `age` fields.

In the generated class, inherited fields come first. To place a field at the end of the combined field list instead, mark it with the `tail` keyword, e.g. `notes: String?, tail`. Tail fields from child classes appear before tail fields from parent classes, and the keyword is not allowed on the `id` field.
In the generated class, inherited fields come first. To change that for a field, mark it with the `tail` keyword. See [Ordering inherited fields](#ordering-inherited-fields).

#### Inheritance on table models

Expand Down Expand Up @@ -73,6 +73,51 @@ As the example shows, indexes can be defined on inherited fields in a child clas

To use a base model that is shared between server and client and extend it on the server with a table, see [Shared packages](./shared-packages).

### Ordering inherited fields

Inherited fields are ordered from the root class down to the child class. Since a base class is declared first, its audit fields end up in front of the fields that describe the child. Mark a field with the `tail` keyword to push it behind every normal field in the hierarchy instead.

Add `tail` after the field type and any other keywords:

```yaml
class: BaseEntity
fields:
ownerId: UuidValue
createdAt: DateTime, default=now, tail
updatedAt: DateTime, default=now, tail
```

Tail ordering applies across the whole hierarchy. Normal fields keep their root-to-child order, and the tail fields follow, starting from the most specific child and working back toward the root parent:

```yaml
class: Document
extends: BaseEntity
fields:
authorName: String
archivedAt: DateTime?, tail
```

```yaml
class: Article
extends: Document
fields:
title: String
publishedAt: DateTime?, tail
```

The generated `Article` class orders its fields like this:

1. `ownerId`, a normal field from the root class.
2. `authorName`, a normal field from the parent class.
3. `title`, a normal field from the child class.
4. `publishedAt`, a tail field from the child class.
5. `archivedAt`, a tail field from the parent class.
6. `createdAt` and `updatedAt`, tail fields from the root class, in the order they are declared.

The same order applies to the generated constructor parameters and the serialized output. For table models it also determines the generated table definition, where the primary `id` column always comes first. The `tail` keyword cannot be used on `id`.

Adding or removing `tail` only affects generated code. It does not rename a database column, and it does not produce a migration that reorders the columns of an existing table.

### Sealed classes

In addition to the `extends` keyword, you can also use the `sealed` keyword to create sealed class hierarchies. The compiler then knows all subclasses, so a `switch` over the model is exhaustive and every possible case must be handled.
Expand Down
2 changes: 1 addition & 1 deletion docs/06-concepts/lookups/model-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Every keyword available in a Serverpod model file, and whether it applies to a `
| [**fields**](../data-and-the-database/models#class) | All fields in the generated class should be listed here. | ✅ | ✅ | |
| [**type (fields)**](../data-and-the-database/models#class) | Denotes the data type for a field. | ✅ | ✅ | |
| [**required**](../data-and-the-database/models#required-fields) | Makes the field required. This keyword can only be used for **nullable** fields. | ✅ | ✅ | |
| [**tail**](../data-and-the-database/models/inheritance-and-polymorphism#extending-a-class) | Places the field at the end of the combined field list when inherited. Not allowed on the `id` field. | ✅ | ✅ | |
| [**tail**](../data-and-the-database/models/inheritance-and-polymorphism#ordering-inherited-fields) | Places the field after all normal fields of an inheritance hierarchy. Child tail fields come before parent tail fields. Not allowed on the `id` field. | ✅ | ✅ | |
| [**scope**](../data-and-the-database/models#limiting-visibility-of-a-generated-class) | Denotes the scope for a field. | ✅ | | |
| [**jsonKey**](../data-and-the-database/models#json-key-aliasing) | Sets a custom key name for JSON serialization and deserialization. | ✅ | | |
| [**column**](../data-and-the-database/database/tables#column-name-override) | Overrides the database column name for a field. | ✅ | | |
Expand Down
Loading