Defining Models
Models are the foundation of every DartWay backend.
They define your domain entities, database schema, and serve as the single source of truth for both server and Flutter apps.
π For the underlying system, DartWay relies fully on Serverpod models.
This document provides a DartWay-specific perspective and rules.
π Basics (Serverpod)β
- Models are defined in
.yamlfiles underlib/src/models/. - Running
dart run serverpod generateproduces:- Dart classes for server & Flutter
- Database schema migrations (after
create-migration)
- Each model defines:
- Fields and their types
- Table name
- Relations (optional)
Example (user_profile.yaml):
class: UserProfile
table: user_profile
fields:
id: int, primary, auto
name: String
email: String, unique
balance: double
createdAt: DateTime
π¦ DartWay Rules for Modelsβ
-
Nullable fields
- Only if the value is truly optional in the domain.
- β Donβt make fields nullable just for editing convenience. Use form states on Flutter side.
-
Base vs Event Models
- Base Models β represent current state of an entity (e.g.
UserProfile). - Event Models β represent changes applied to base models (e.g.
BalanceEvent).- Prevent concurrent update issues
- Provide traceability (audit log)
- Centralize complex business rules (fees, limits)
Example (
balance_event.yaml):class: BalanceEvent
table: balance_event
fields:
id: int, primary, auto
userId: int, relation(parent=user_profile)
amount: double
reason: String
createdAt: DateTime - Base Models β represent current state of an entity (e.g.
-
Consistency across server & client
- Generated Flutter models must be used directly β no hand-written duplicates.
- Use extensions in
/domainfor business logic (e.g. computed getters).
-
Relations
- Always define explicit relations in YAML.
- Supported: 1β1, 1βN, NβN.
- Prefer
relation(parent=...)orrelation(name=...)to ensure schema consistency.
Bidirectional Relationsβ
For bidirectional relations between models, use the following pattern:
Parent side (one-to-many):
- Use
List<ChildModel>?field type - Use
relation(name=relation_name)syntax - Example:
comments: List<PostComment>?, relation(name=post_comments)
Child side (many-to-one):
- Use the actual parent model type (not ID)
- Use
relation(name=relation_name)with the same name as parent - Example:
appPost: AppPost, relation(name=post_comments)
Both sides must use the same relation_name to establish the bidirectional connection.
π Workflow with Modelsβ
- Define or edit a YAML model in
/models. - Generate code:
dart run serverpod generate - Create migration:
dart run serverpod create-migrationwarningIf schema changed heavily,
--forcemay be required. Use with care β it overwrites previous migrations. - Migrations will be applied automatically at server startup with the
--apply-migrationsflag. - Configure CRUD behavior in
/crud. - Extend business rules in
/domainor workflows in/app.
β Key Takeawaysβ
- Models are the single source of truth.
- Nullable only if business domain allows it.
- Use Event Models for transactional safety and audit.
- Define explicit relations.
- Always regenerate & migrate after changes.
- For details, see the Serverpod Models Documentation.