Structs
Rather than using a separate service for each type of entity in your system, sometimes it makes sense to store multiple types of entity on the same database. This is useful for implementing many-to-one relationships, providing a parallel to arrays. Temple provides this functionality in the form of structs. A struct block is expressed in the Templefile as a block within another service.
Example: project {#provider(kube);#authMethod(email);}Home: service {address: string;occupants: int(min: 0, precision: 1);#auth;Room: struct {name: string;#enumerable;};}
Every struct entry has an implicit reference to an entity in the parent service. In the example above, every room is part of a single home.
Structs may include metadata for specifying which endpoints are generated: #enumerable
and #omit[...]
.
They may not include access control metadata (#readable
/#writable
): this is all inherited from the parent.
This means that, if a service is only writable by the creator, only the creator of the service entry may create a struct tied to this service entity.
The struct entry is likewise only readable (through the list/read endpoints) if the parent is readable.
Many-to-many relationships
To make a many-to-many relationship, use a struct as a linking table.
Below are two examples of this.
Note that in the second example, Follower
does not include a reference to the tweeter doing the following, as that is implicit: only the reference to the tweeter being followed is included.
ExampleNews: project {}Subscriber: service {username: string @unique;Subscription: struct {topic: Topic;#enumerable;};}Topic: service {title: string @unique;}
ExampleNetwork: project {}Tweeter: service {username: string @unique;Follower: struct {otherTweeter: Tweeter;#enumerable;};}
Endpoint URLs
To emphasize that every struct is tied to a specific instance of the service, the ID of the parent is included in the URL of the entry.
Using the example above, the endpoints generated are as follows:
- Create:
POST /api/home/{parent-id}/room
- Read:
GET /api/home/{parent-id}/room/{id}
- Update:
PUT /api/home/{parent-id}/room/{id}
- Delete:
DELETE /api/home/{parent-id}/room/{id}
- List:
GET /api/home/{parent-id}/room/{id}/all
For example, if we have a home with ID 82abd10c-8b90-11ea-bc55-0242ac130003
, we can create a room with a POST to /api/home/82abd10c-8b90-11ea-bc55-0242ac130003/room
.
If this returns a room with ID 019103d4-8b96-11ea-bc55-0242ac130003
, we can read it with a GET to /api/home/82abd10c-8b90-11ea-bc55-0242ac130003/room/019103d4-8b96-11ea-bc55-0242ac130003
.