What this is about
If you send a list field, for example employees on a company, the list describes the state afterwards: The list should have exactly these members. So the list is not an “add this”. It is a target state.
Before and after
flowchart LR
subgraph vorher ["before: employees"]
A1[Anna]
B1[Ben]
C1[Cem]
end
subgraph payload ["in the request"]
A2["{ id: Anna }"]
C2["{ id: Cem }"]
D2["{ firstname: Dora }"]
end
subgraph nachher ["after: employees"]
A3[Anna]
C3[Cem]
D3["Dora (new)"]
end
vorher --> payload --> nachher
| Member | before | in the request | after |
|---|---|---|---|
| Anna | yes | with id | stays |
| Ben | yes | missing | gets removed: deleted (DELETE flag) or detached |
| Cem | yes | with id | stays |
| Dora | no | without id | is created (needs CREATE) |
What happens to a removed member
When: The relation employees has the DELETE flag, Ben is a dependent child.
-
1CDMSchecks the delete role of the employee model
-
2HookBen's DELETE hooks run
-
3CDMS→Databasedeletes Ben, together with his own dependent children and files
Result: Ben no longer exists, read returns 404.
When: The relation items of an invoice has no DELETE flag, the items are independent.
-
1CDMS→Databasesets the field of the other side on the item to empty, that is
sponsorInvoice = null -
2CDMSthe item itself stays
Result: The item is detached: It still exists, but no longer belongs to any invoice. This does not need a role on the item model.
When: A role is removed from groups, the relation has no DELETE flag.
-
1CDMS→Databasedeletes the row in the join table
Result: Both objects stay, only their connection is gone.
When: A role is removed from the roles of a group, the relation has the DELETE flag.
-
1CDMS→Databasedeletes the row in the join table, just as without the flag
Result: The role stays, also for all other groups. DELETE has no effect on n:m, because the member can belong to other partners as well. See Many-to-many through a join table.
The list step by step
-
1CDMScollects the
ids of all entries in the request -
2CDMSremoves every previous member whose
idis not included from the list: delete (DELETE) or detach -
3CDMSentries with
id: link or update along, depending on flag and verb -
4CDMSentries without
id: create new, if the relation has CREATE -
5CDMS→Databasesaves everything in one transaction
How entries with and without id are handled is described in The four cases in nested writing.
Empty list, missing list
| Verb | List field in the request | Result |
|---|---|---|
| PUT | missing | all members removed |
| PUT | null or [] | all members removed |
| PATCH | missing | unchanged |
| PATCH | null or [] | all members removed |
| PUT, PATCH | partial list | exactly these members |
| Create | missing, null or [] | empty list |
For every member, “removed” means: deleted with the DELETE flag, otherwise detached.
Order and duplicate entries
- Order: A list in CDMS is a set, without positions. The order in the request is not saved. When you read, you set the order with
orderin theresponseof the list. Otherwise the order is not defined. See Filters in nested lists. - Duplicate entries: Two identical entries without
idcreate two objects with Create and PUT, and one with PATCH. The sameidtwice with different values: the last entry wins. Send each member only once.
Pitfalls
What comes next
- With and without
id: The four cases in nested writing - Deleting and cascades: Dependent objects (cascades)
- PUT and PATCH: PUT or PATCH? The null trap