Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Create/Update/Upsert directives to DRY
- Loading branch information
Jose Manuel Cardona
committed
Oct 13, 2019
1 parent
b48d1a6
commit 87eec45
Showing
14 changed files
with
305 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,6 +218,56 @@ may fail to find the model you provided and return `null`: | |
} | ||
``` | ||
|
||
## Upsert | ||
|
||
You can create or update a model with the [@upsert](../api-reference/directives.md#upsert) directive. | ||
|
||
```graphql | ||
type Mutation { | ||
upsertUser(id: ID!, name: String!, email: String): User @upsert | ||
} | ||
``` | ||
|
||
Since upsert can create or update your data you must have all the minimum fields for a creation as required. | ||
For example the `id` is going to be always mandatory. | ||
|
||
```graphql | ||
mutation { | ||
upsertUser(id: "123" name: "Hillary"){ | ||
id | ||
name | ||
} | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"data": { | ||
"upsertUser": { | ||
"id": "123", | ||
"name": "Hillary", | ||
"email": null | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Due to upsert does a create or update, it produces an idempotent result. This means that you can execute it | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
joskfg
Collaborator
|
||
as many times as you want, that it will produce always the same result. | ||
|
||
```json | ||
{ | ||
"data": { | ||
"upsertUser": { | ||
"id": "123", | ||
"name": "Hillary", | ||
"email": null | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Delete | ||
|
||
Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. Dangerously easy. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,13 +66,15 @@ input CreateAuthorRelation { | |
connect: ID | ||
create: CreateUserInput | ||
update: UpdateUserInput | ||
upsert: UpsertUserInput | ||
} | ||
``` | ||
|
||
There are 3 possible operations that you can expose on a `BelongsTo` relationship when creating: | ||
This comment has been minimized.
Sorry, something went wrong.
spawnia
Collaborator
|
||
- `connect` it to an existing model | ||
- `create` a new related model and attach it | ||
- `update` an existing model and attach it | ||
- `upsert` a new or an existing model and attach it | ||
|
||
Finally, you need to define the input that allows you to create a new `User`. | ||
|
||
|
@@ -160,6 +162,7 @@ type Mutation { | |
} | ||
|
||
input UpdatePostInput { | ||
id: ID! | ||
This comment has been minimized.
Sorry, something went wrong. |
||
title: String | ||
author: UpdateAuthorRelation | ||
} | ||
|
@@ -180,6 +183,7 @@ and allows the query string to be mostly static, taking a variable value to cont | |
```graphql | ||
mutation UpdatePost($disconnectAuthor: Boolean){ | ||
updatePost(input: { | ||
id: 1 | ||
title: "An updated title" | ||
author: { | ||
disconnect: $disconnectAuthor | ||
|
@@ -200,13 +204,47 @@ The `author` relationship will only be disconnected if the value of the variable | |
{ | ||
"data": { | ||
"updatePost": { | ||
"id": 1, | ||
"title": "An updated title", | ||
"author": null | ||
} | ||
} | ||
} | ||
``` | ||
|
||
When issuing an upsert you will have all the update options, so the behaviour is the same. In the case that | ||
you create a new model it will have the same behaviour than an update that doesn't have any connected model. | ||
|
||
```graphql | ||
mutation UpdatePost($disconnectAuthor: Boolean){ | ||
upsertPost(input: { | ||
id: 1 | ||
title: "An updated or created title" | ||
author: { | ||
disconnect: $disconnectAuthor | ||
} | ||
}){ | ||
id | ||
title | ||
author { | ||
name | ||
} | ||
} | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"data": { | ||
"upsertPost": { | ||
"id": 1, | ||
"title": "An updated or created title", | ||
"author": null | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Has Many | ||
|
||
The counterpart to a `BelongsTo` relationship is `HasMany`. We will start | ||
|
@@ -304,6 +342,7 @@ input UpdateUserInput { | |
input UpdatePostsRelation { | ||
create: [CreatePostInput!] | ||
update: [UpdatePostInput!] | ||
upsert: [UpsertPostInput!] | ||
delete: [ID!] | ||
} | ||
|
||
|
@@ -315,6 +354,11 @@ input UpdatePostInput { | |
id: ID! | ||
title: String | ||
} | ||
|
||
input UpsertPostInput { | ||
id: ID! | ||
title: String | ||
} | ||
``` | ||
|
||
```graphql | ||
|
@@ -347,6 +391,9 @@ mutation { | |
} | ||
``` | ||
|
||
The behaviour when you are upserting is a mix between updating and creating and it won't fail | ||
if the model exists or not because it will produce the needed action (update or create) in every case. | ||
|
||
## Belongs To Many | ||
|
||
A belongs to many relation allows you to create new related models as well | ||
|
@@ -364,13 +411,19 @@ input CreatePostInput { | |
|
||
input CreateAuthorRelation { | ||
create: [CreateAuthorInput!] | ||
upsert: [UpsertAuthorInput!] | ||
connect: [ID!] | ||
sync: [ID!] | ||
} | ||
|
||
input CreateAuthorInput { | ||
name: String! | ||
} | ||
|
||
input UpsertAuthorInput { | ||
id: ID! | ||
name: String! | ||
} | ||
``` | ||
|
||
Just pass the ID of the models you want to associate or their full information | ||
|
@@ -386,6 +439,12 @@ mutation { | |
name: "Herbert" | ||
} | ||
] | ||
upsert: [ | ||
{ | ||
id: 2000 | ||
name: "Newton" | ||
} | ||
] | ||
connect: [ | ||
123 | ||
] | ||
|
@@ -399,7 +458,7 @@ mutation { | |
} | ||
``` | ||
|
||
Lighthouse will detect the relationship and attach/create it. | ||
Lighthouse will detect the relationship and attach/update/create it. | ||
|
||
```json | ||
{ | ||
|
@@ -411,6 +470,10 @@ Lighthouse will detect the relationship and attach/create it. | |
"id": 165, | ||
"name": "Herbert" | ||
}, | ||
{ | ||
"id": 2000, | ||
"name": "Newton" | ||
}, | ||
{ | ||
"id": 123, | ||
"name": "Franz" | ||
|
@@ -442,7 +505,7 @@ mutation { | |
} | ||
``` | ||
|
||
Updates on BelongsToMany relations may expose up to 6 nested operations. | ||
Updates on BelongsToMany relations may expose up to 7 nested operations. | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
```graphql | ||
type Mutation { | ||
|
@@ -459,6 +522,7 @@ input UpdateAuthorRelation { | |
create: [CreateAuthorInput!] | ||
connect: [ID!] | ||
update: [UpdateAuthorInput!] | ||
upsert: [UpsertAuthorInput!] | ||
sync: [ID!] | ||
delete: [ID!] | ||
disconnect: [ID!] | ||
|
@@ -472,6 +536,11 @@ input UpdateAuthorInput { | |
id: ID! | ||
name: String! | ||
} | ||
|
||
input UpsertAuthorInput { | ||
id: ID! | ||
name: String! | ||
} | ||
``` | ||
|
||
## MorphTo | ||
|
@@ -495,6 +564,7 @@ type Hour { | |
type Mutation { | ||
createHour(input: CreateHourInput! @spread): Hour @create | ||
updateHour(input: UpdateHourInput! @spread): Hour @update | ||
upsertHour(input: UpsertHourInput! @spread): Hour @upsert | ||
} | ||
|
||
input CreateHourInput { | ||
|
@@ -512,6 +582,14 @@ input UpdateHourInput { | |
hourable: UpdateHourableOperations | ||
} | ||
|
||
input UpsertHourInput { | ||
id: ID! | ||
from: String | ||
to: String | ||
weekday: Int | ||
hourable: UpsertHourableOperations | ||
} | ||
|
||
input CreateHourableOperations { | ||
connect: ConnectHourableInput | ||
} | ||
|
@@ -522,6 +600,12 @@ input UpdateHourableOperations { | |
delete: Boolean | ||
} | ||
|
||
input UpsertHourableOperations { | ||
connect: ConnectHourableInput | ||
disconnect: Boolean | ||
delete: Boolean | ||
} | ||
|
||
input ConnectHourableInput { | ||
type: String! | ||
id: ID! | ||
|
@@ -575,7 +659,7 @@ The `delete` operation both detaches and deletes the currently associated model. | |
|
||
```graphql | ||
mutation { | ||
updateHour(input: { | ||
upsertHour(input: { | ||
id: 1 | ||
weekday: 2 | ||
hourable: { | ||
|
@@ -608,6 +692,7 @@ input CreateTaskInput { | |
|
||
input CreateTagRelation { | ||
create: [CreateTagInput!] | ||
upsert: [UpsertTagInput!] | ||
sync: [ID!] | ||
connect: [ID!] | ||
} | ||
|
@@ -616,6 +701,12 @@ input CreateTagInput { | |
name: String! | ||
} | ||
|
||
input UpsertTagInput { | ||
id: ID! | ||
name: String! | ||
} | ||
|
||
|
||
type Task { | ||
id: ID! | ||
name: String! | ||
|
@@ -649,7 +740,8 @@ mutation { | |
You can either use `connect` or `sync` during creation. | ||
|
||
When you want to create a new tag while creating the task, | ||
you need use the `create` operation to provide an array of `CreateTagInput`: | ||
you need use the `create` operation to provide an array of `CreateTagInput` | ||
or use the `upsert` operation to provide an array of `UpsertTagInput`: | ||
|
||
```graphql | ||
mutation { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
That is not necessarily true, as timestamps may be updated.
I think we can just skip that section, the docs are clear regardless.