Skip to content

Commit 29058d4

Browse files
committed
Add guides for class-based mutations
1 parent 9dd17fa commit 29058d4

File tree

4 files changed

+131
-5
lines changed

4 files changed

+131
-5
lines changed

guides/css/main.scss

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ pre {
9898
border: 1px solid $code-border;
9999
border-radius: $code-border-radius;
100100
background-color: $code-background;
101-
margin: 10px 0px;
101+
margin: 20px 0px;
102102
overflow-x: scroll;
103+
line-height: 1.4rem;
103104
}
104105

105106
p, li {
@@ -110,10 +111,6 @@ li {
110111
margin-left: 15px;
111112
}
112113

113-
pre {
114-
line-height: 1.4rem;
115-
}
116-
117114
p, ul {
118115
margin-bottom: 10px;
119116
}
@@ -182,9 +179,11 @@ a:hover, a:hover code {
182179
ul {
183180
list-style: none;
184181
display: flex;
182+
flex-wrap: wrap;
185183
}
186184

187185
li {
186+
padding-bottom: 10px;
188187
padding-right: 10px;
189188
}
190189
}

guides/guides.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- name: Types
77
- name: Type Definitions
88
- name: Fields
9+
- name: Mutations
910
- name: Relay
1011
- name: Subscriptions
1112
- name: GraphQL Pro

guides/mutations/mutation_classes.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
layout: guide
3+
search: true
4+
section: Mutations
5+
title: Mutation Classes
6+
desc: Use mutation classes to implement behavior, then hook them up to your schema.
7+
class_based_api: true
8+
index: 1
9+
---
10+
11+
GraphQL _mutations_ are special fields: instead of reading data or performing calculations, they may _modify_ the application state. For example, mutation fields may:
12+
13+
- Create, update or destroy records in the database
14+
- Establish associations between already-existing records in the database
15+
- Increment counters
16+
- Create, modify or delete files
17+
- Clear caches
18+
19+
These actions are called _side effects_.
20+
21+
Like all GraphQL fields, mutation fields:
22+
23+
- Accept inputs, called _arguments_
24+
- Return values via _fields_
25+
26+
GraphQL-Ruby includes two classes to help you write mutations:
27+
28+
- {{ "GraphQL::Schema::Mutation" | api_doc }}, a bare-bones base class
29+
- {{ "GraphQL::Schema::RelayClassicMutation" | api_doc }}, a base class with a set of nice conventions that also supports the Relay Classic mutation specification.
30+
31+
Besides those, you can also use the plain {% internal_link "field API", "/type_definitions/objects#fields" %} to write mutation fields.
32+
33+
## Example mutation class
34+
35+
You should add a base class to your application, for example:
36+
37+
```ruby
38+
class Mutations::BaseMutation < GraphQL::Schema::RelayClassicMutation
39+
end
40+
```
41+
42+
Then extend it for your mutations:
43+
44+
```ruby
45+
class Mutations::CreateComment < Mutations::BaseMutation
46+
argument :body, String, required: true
47+
argument :post_id, ID, required: true
48+
49+
field :comment, Types::Comment, null: true
50+
field :error_messages, [String], null: false
51+
52+
def resolve(body:, post_id:)
53+
post = Post.find(post_id)
54+
comment = post.comments.build(body: body, author: context[:current_user])
55+
if comment.save
56+
# Successful creation, return the created object with no errors
57+
{
58+
comment: comment,
59+
errors: [],
60+
}
61+
else
62+
# Failed save, return the errors to the client
63+
{
64+
comment: nil,
65+
errors: comment.errors.full_messages
66+
}
67+
end
68+
end
69+
end
70+
```
71+
72+
The `#resolve` method should return a hash whose symbols match the `field` names.
73+
74+
## Hooking up mutations
75+
76+
Mutations must be attached to the mutation root using the `mutation:` keyword, for example:
77+
78+
```ruby
79+
class Types::Mutation < Types::BaseObject
80+
field :create_comment, mutation: Mutations::CreateComment
81+
end
82+
```

guides/mutations/mutation_root.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
layout: guide
3+
search: true
4+
section: Mutations
5+
title: Mutation Root
6+
desc: The Mutation object is the entry point for mutation operations.
7+
class_based_api: true
8+
index: 0
9+
---
10+
11+
GraphQL mutations all begin with the `mutation` keyword:
12+
13+
```graphql
14+
mutation($accountNumber: ID!, $newBalance: Int!) {
15+
# ^^^^ here
16+
setAccountBalance(accountNumber: $accountNumber, newBalance: $newBalance) {
17+
# ...
18+
}
19+
}
20+
```
21+
22+
Operations that begin with `mutation` get special treatment by the GraphQL runtime: root fields are guaranteed
23+
to be executed sequentially. This way, the effect of a series of mutations is predictable.
24+
25+
Mutations are executed by a specific GraphQL object, `Mutation`. This object is defined like any other GraphQL object:
26+
27+
```ruby
28+
class Types::Mutation < Types::BaseObject
29+
# ...
30+
end
31+
```
32+
33+
Then, it must be attached to your schema with the `mutation(...)` configuration:
34+
35+
```ruby
36+
class Schema < GraphQL::Schema
37+
# ...
38+
mutation(Types::Mutation)
39+
end
40+
```
41+
42+
Now, whenever an incoming request uses the `mutation` keyword, it will go to `Mutation`.
43+
44+
See {% internal_link "Mutation Classes", "/mutations/mutation_classes" %} for some helpers to define mutation fields.

0 commit comments

Comments
 (0)