Skip to content

Commit cc57a60

Browse files
committed
add better documentation on relationship metadata
1 parent ce52882 commit cc57a60

1 file changed

Lines changed: 35 additions & 21 deletions

File tree

documentation/usage.md

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ In this documentation, in order to draw attention to the difference between the
1111
- [`RawIdType`](#rawidtype)
1212
- [Convenient `typealiases`](#convenient-typealiases)
1313
- [`JSONAPI.Relationships`](#jsonapirelationships)
14+
- [Relationship Metadata](#relationship-metadata)
1415
- [`JSONAPI.Attributes`](#jsonapiattributes)
1516
- [`Transformer`](#transformer)
1617
- [`Validator`](#validator)
@@ -149,6 +150,33 @@ Note that I am calling an unidentified person is a "new" person. This is general
149150

150151
There are three types of `Relationships`: `MetaRelationship`, `ToOneRelationship` and `ToManyRelationship`. A `ResourceObjectDescription`'s `Relationships` type can contain any number of `Relationship` properties of any of these types. Do not store anything other than `Relationship` properties in the `Relationships` struct of a `ResourceObjectDescription`.
151152

153+
The `MetaRelationship` is special in that it represents a Relationship Object with no `data` (it must contain at least one of `meta` or `links`). The other two relationship types are Relationship Objects with either singular resource linkages (`ToOneRelationship`) or arrays of resource linkages (`ToManyRelationship`).
154+
155+
To describe a relationship that may be omitted (i.e. the key is not even present in the JSON object), you make the entire `MetaRelationship`, `ToOneRelationship` or `ToManyRelationship` optional.
156+
```swift
157+
// note the question mark at the very end of the line.
158+
let optionalRelative: ToOneRelationship<Person, NoIdMetadata, NoMetadata, NoLinks>?
159+
```
160+
161+
A `ToOneRelationship` can be marked as nullable (i.e. the value could be either `null` or a resource identifier) like this:
162+
```swift
163+
// note the question mark just after `Person`.
164+
let nullableRelative: ToOneRelationship<Person?, NoIdMetadata, NoMetadata, NoLinks>
165+
```
166+
167+
A `ToManyRelationship` can naturally represent the absence of related values with an empty array, so `ToManyRelationship` do not support nullability.
168+
169+
A `ResourceObject` that does not have relationships can be described by adding the following to a `ResourceObjectDescription`:
170+
```swift
171+
typealias Relationships = NoRelationships
172+
```
173+
174+
`Relationship` values boil down to `Ids` of other resource objects. To access the `Id` of a related `ResourceObject`, you can use the custom `~>` operator with the `KeyPath` of the `Relationship` from which you want the `Id`. The friends of the above `Person` `ResourceObject` can be accessed as follows (type annotations for clarity):
175+
```swift
176+
let friendIds: [Person.Id] = person ~> \.friends
177+
```
178+
179+
#### Relationship Metadata
152180
In addition to identifying resource objects by ID and type, `Relationships` can contain `Meta` or `Links` that follow the same rules as [`Meta`](#jsonapimeta) and [`Links`](#jsonapilinks) elsewhere in the JSON:API Document.
153181

154182
Metadata can be specified both in the Relationship Object and in the Resource Identifier Object. You specify the two types of metadata differently. As always, you can use `NoMetadata` to indicate you do not intend the JSON:API relationship to contain metadata.
@@ -186,30 +214,16 @@ let relationship3: ToOneRelationship<Person, CoolMetadata, NoMetadata, NoLinks>
186214
// ^ assumes `CoolMetadata` is a `Codable` struct defined elsewhere
187215
```
188216

189-
The `MetaRelationship` is special in that it represents a Relationship Object with no `data` (it must contain at least one of `meta` or `links`). The other two relationship types are Relationship Objects with either singular resource linkages (`ToOneRelationship`) or arrays of resource linkages (`ToManyRelationship`).
217+
When you need metadata out of a to-one relationship, you can access the Relationship Object metadata with the `meta` property and the Resource Identifer metadata with the `idMeta` property. When you need metadata out of a to-many relationship, you can access the Relationship Object metadata with the `meta` property (there is only one such metadata object) and you can access the Resource Identifier metadata (of which there is one per related resource) by asking each element of the `idsWithMeta` property for its `meta` property.
190218

191-
To describe a relationship that may be omitted (i.e. the key is not even present in the JSON object), you make the entire `MetaRelationship`, `ToOneRelationship` or `ToManyRelationship` optional.
192219
```swift
193-
// note the question mark at the very end of the line.
194-
let optionalRelative: ToOneRelationship<Person, NoIdMetadata, NoMetadata, NoLinks>?
195-
```
220+
// to-one
221+
let relation = entity.relationships.home
222+
let idMeta = relation.idMeta
196223

197-
A `ToOneRelationship` can be marked as nullable (i.e. the value could be either `null` or a resource identifier) like this:
198-
```swift
199-
// note the question mark just after `Person`.
200-
let nullableRelative: ToOneRelationship<Person?, NoIdMetadata, NoMetadata, NoLinks>
201-
```
202-
203-
A `ToManyRelationship` can naturally represent the absence of related values with an empty array, so `ToManyRelationship` do not support nullability.
204-
205-
A `ResourceObject` that does not have relationships can be described by adding the following to a `ResourceObjectDescription`:
206-
```swift
207-
typealias Relationships = NoRelationships
208-
```
209-
210-
`Relationship` values boil down to `Ids` of other resource objects. To access the `Id` of a related `ResourceObject`, you can use the custom `~>` operator with the `KeyPath` of the `Relationship` from which you want the `Id`. The friends of the above `Person` `ResourceObject` can be accessed as follows (type annotations for clarity):
211-
```swift
212-
let friendIds: [Person.Id] = person ~> \.friends
224+
// to-many
225+
let relations = entity.relationships.friends
226+
let idMeta = relations.idsWithMeta.map { $0.meta }
213227
```
214228

215229
### `JSONAPI.Attributes`

0 commit comments

Comments
 (0)