monday_ruby 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env +1 -1
- data/.rspec +0 -1
- data/.rubocop.yml +19 -0
- data/.simplecov +1 -0
- data/CHANGELOG.md +49 -0
- data/CONTRIBUTING.md +165 -0
- data/README.md +167 -88
- data/docs/.vitepress/config.mjs +255 -0
- data/docs/.vitepress/theme/index.js +4 -0
- data/docs/.vitepress/theme/style.css +43 -0
- data/docs/README.md +80 -0
- data/docs/explanation/architecture.md +507 -0
- data/docs/explanation/best-practices/errors.md +478 -0
- data/docs/explanation/best-practices/performance.md +1084 -0
- data/docs/explanation/best-practices/rate-limiting.md +630 -0
- data/docs/explanation/best-practices/testing.md +820 -0
- data/docs/explanation/column-values.md +857 -0
- data/docs/explanation/design.md +795 -0
- data/docs/explanation/graphql.md +356 -0
- data/docs/explanation/migration/v1.md +808 -0
- data/docs/explanation/pagination.md +447 -0
- data/docs/guides/advanced/batch.md +1274 -0
- data/docs/guides/advanced/complex-queries.md +1114 -0
- data/docs/guides/advanced/errors.md +818 -0
- data/docs/guides/advanced/pagination.md +934 -0
- data/docs/guides/advanced/rate-limiting.md +981 -0
- data/docs/guides/authentication.md +286 -0
- data/docs/guides/boards/create.md +386 -0
- data/docs/guides/boards/delete.md +405 -0
- data/docs/guides/boards/duplicate.md +511 -0
- data/docs/guides/boards/query.md +530 -0
- data/docs/guides/boards/update.md +453 -0
- data/docs/guides/columns/create.md +452 -0
- data/docs/guides/columns/metadata.md +492 -0
- data/docs/guides/columns/query.md +455 -0
- data/docs/guides/columns/update-multiple.md +459 -0
- data/docs/guides/columns/update-values.md +509 -0
- data/docs/guides/files/add-to-column.md +40 -0
- data/docs/guides/files/add-to-update.md +37 -0
- data/docs/guides/files/clear-column.md +33 -0
- data/docs/guides/first-request.md +285 -0
- data/docs/guides/folders/manage.md +750 -0
- data/docs/guides/groups/items.md +626 -0
- data/docs/guides/groups/manage.md +501 -0
- data/docs/guides/installation.md +169 -0
- data/docs/guides/items/create.md +493 -0
- data/docs/guides/items/delete.md +514 -0
- data/docs/guides/items/query.md +605 -0
- data/docs/guides/items/subitems.md +483 -0
- data/docs/guides/items/update.md +699 -0
- data/docs/guides/updates/manage.md +619 -0
- data/docs/guides/use-cases/dashboard.md +1421 -0
- data/docs/guides/use-cases/import.md +1962 -0
- data/docs/guides/use-cases/task-management.md +1381 -0
- data/docs/guides/workspaces/manage.md +502 -0
- data/docs/index.md +69 -0
- data/docs/package-lock.json +2468 -0
- data/docs/package.json +13 -0
- data/docs/reference/client.md +540 -0
- data/docs/reference/configuration.md +586 -0
- data/docs/reference/errors.md +693 -0
- data/docs/reference/resources/account.md +208 -0
- data/docs/reference/resources/activity-log.md +369 -0
- data/docs/reference/resources/board-view.md +359 -0
- data/docs/reference/resources/board.md +393 -0
- data/docs/reference/resources/column.md +543 -0
- data/docs/reference/resources/file.md +236 -0
- data/docs/reference/resources/folder.md +386 -0
- data/docs/reference/resources/group.md +507 -0
- data/docs/reference/resources/item.md +348 -0
- data/docs/reference/resources/subitem.md +267 -0
- data/docs/reference/resources/update.md +259 -0
- data/docs/reference/resources/workspace.md +213 -0
- data/docs/reference/response.md +560 -0
- data/docs/tutorial/first-integration.md +713 -0
- data/lib/monday/client.rb +41 -2
- data/lib/monday/configuration.rb +13 -0
- data/lib/monday/deprecation.rb +23 -0
- data/lib/monday/error.rb +5 -2
- data/lib/monday/request.rb +19 -1
- data/lib/monday/resources/base.rb +4 -0
- data/lib/monday/resources/board.rb +52 -0
- data/lib/monday/resources/column.rb +6 -0
- data/lib/monday/resources/file.rb +56 -0
- data/lib/monday/resources/folder.rb +55 -0
- data/lib/monday/resources/group.rb +66 -0
- data/lib/monday/resources/item.rb +62 -0
- data/lib/monday/util.rb +33 -1
- data/lib/monday/version.rb +1 -1
- data/lib/monday_ruby.rb +1 -0
- metadata +92 -11
- data/monday_ruby.gemspec +0 -39
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
# Response
|
|
2
|
+
|
|
3
|
+
The `Monday::Response` class wraps HTTP responses from the monday.com API.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Every request to monday.com returns a `Monday::Response` object that encapsulates the HTTP response status, parsed JSON body, and headers. This wrapper provides convenient access to response data and helps detect errors.
|
|
8
|
+
|
|
9
|
+
All resource methods (`client.board.query`, `client.item.create`, etc.) return a `Monday::Response` object.
|
|
10
|
+
|
|
11
|
+
## Attributes
|
|
12
|
+
|
|
13
|
+
All attributes are read-only (`attr_reader`).
|
|
14
|
+
|
|
15
|
+
| Attribute | Type | Description |
|
|
16
|
+
|-----------|------|-------------|
|
|
17
|
+
| `status` | Integer | HTTP status code (200, 400, 401, 404, 500, etc.) |
|
|
18
|
+
| `body` | Hash | Parsed JSON response body containing GraphQL data |
|
|
19
|
+
| `headers` | Hash | HTTP response headers as key-value pairs |
|
|
20
|
+
|
|
21
|
+
**Example:**
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
response = client.board.query(args: { ids: [123] })
|
|
25
|
+
|
|
26
|
+
response.status # => 200
|
|
27
|
+
response.body # => { "data" => { "boards" => [...] } }
|
|
28
|
+
response.headers # => { "content-type" => "application/json", ... }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Methods
|
|
32
|
+
|
|
33
|
+
### success?
|
|
34
|
+
|
|
35
|
+
Determines if the request was successful.
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
response.success? # => true or false
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Returns:** Boolean
|
|
42
|
+
|
|
43
|
+
::: warning <span style="display: inline-flex; align-items: center; gap: 6px;"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>monday.com API Quirk</span>
|
|
44
|
+
monday.com returns HTTP 200 status codes even for some GraphQL errors. The `success?` method checks BOTH the status code (200-299) AND the response body for error keys.
|
|
45
|
+
:::
|
|
46
|
+
|
|
47
|
+
**Error Detection:**
|
|
48
|
+
|
|
49
|
+
The method returns `false` if:
|
|
50
|
+
- HTTP status code is outside 200-299 range, OR
|
|
51
|
+
- Response body contains any of these keys: `"errors"`, `"error_code"`, `"error_message"`
|
|
52
|
+
|
|
53
|
+
**Example:**
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
response = client.board.query(args: { ids: [123] })
|
|
57
|
+
|
|
58
|
+
if response.success?
|
|
59
|
+
# Safe to access data
|
|
60
|
+
boards = response.body.dig("data", "boards")
|
|
61
|
+
else
|
|
62
|
+
# Handle error
|
|
63
|
+
errors = response.body["errors"]
|
|
64
|
+
end
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Response Structure
|
|
68
|
+
|
|
69
|
+
### Successful GraphQL Response
|
|
70
|
+
|
|
71
|
+
All successful GraphQL responses follow this structure:
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
{
|
|
75
|
+
"data" => {
|
|
76
|
+
"boards" => [
|
|
77
|
+
{ "id" => "123", "name" => "My Board" }
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"account_id" => 12345678
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The actual data is nested under the `"data"` key, with the resource name as the next level.
|
|
85
|
+
|
|
86
|
+
**Common GraphQL response patterns:**
|
|
87
|
+
|
|
88
|
+
| Operation | Path to data |
|
|
89
|
+
|-----------|--------------|
|
|
90
|
+
| Query boards | `response.body.dig("data", "boards")` |
|
|
91
|
+
| Create board | `response.body.dig("data", "create_board")` |
|
|
92
|
+
| Query items | `response.body.dig("data", "items")` |
|
|
93
|
+
| Create item | `response.body.dig("data", "create_item")` |
|
|
94
|
+
| Duplicate board | `response.body.dig("data", "duplicate_board", "board")` |
|
|
95
|
+
|
|
96
|
+
### Error Response
|
|
97
|
+
|
|
98
|
+
Error responses contain an `"errors"` array:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
{
|
|
102
|
+
"errors" => [
|
|
103
|
+
{
|
|
104
|
+
"message" => "User unauthorized to perform action",
|
|
105
|
+
"extensions" => {
|
|
106
|
+
"code" => "AuthorizationException",
|
|
107
|
+
"error_code" => "AuthorizationException"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"account_id" => 12345678
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Alternative error formats:
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
# Simple error
|
|
119
|
+
{
|
|
120
|
+
"error_message" => "Invalid token",
|
|
121
|
+
"error_code" => "InvalidTokenException"
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# Generic error
|
|
125
|
+
{
|
|
126
|
+
"errors" => "Some error message"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Accessing Data
|
|
131
|
+
|
|
132
|
+
### Using dig for Safe Access
|
|
133
|
+
|
|
134
|
+
Always use `dig` to safely navigate nested response data:
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
response = client.board.query(args: { ids: [123] })
|
|
138
|
+
|
|
139
|
+
# Safe - returns nil if any key is missing
|
|
140
|
+
boards = response.body.dig("data", "boards")
|
|
141
|
+
|
|
142
|
+
# Unsafe - raises error if key is missing
|
|
143
|
+
boards = response.body["data"]["boards"] # Don't do this
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Accessing Nested Data
|
|
147
|
+
|
|
148
|
+
**Single board:**
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
response = client.board.query(args: { ids: [123] })
|
|
152
|
+
|
|
153
|
+
boards = response.body.dig("data", "boards")
|
|
154
|
+
board = boards&.first
|
|
155
|
+
|
|
156
|
+
puts board["name"] # => "My Board"
|
|
157
|
+
puts board["id"] # => "123"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Board with items:**
|
|
161
|
+
|
|
162
|
+
```ruby
|
|
163
|
+
response = client.board.query(
|
|
164
|
+
args: { ids: [123] },
|
|
165
|
+
select: ["id", "name", { items: ["id", "name"] }]
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
board = response.body.dig("data", "boards", 0)
|
|
169
|
+
items = board["items"]
|
|
170
|
+
|
|
171
|
+
items.each do |item|
|
|
172
|
+
puts item["name"]
|
|
173
|
+
end
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Paginated items:**
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
179
|
+
response = client.board.items_page(
|
|
180
|
+
board_ids: 123,
|
|
181
|
+
limit: 50
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
items_page = response.body.dig("data", "boards", 0, "items_page")
|
|
185
|
+
items = items_page["items"]
|
|
186
|
+
cursor = items_page["cursor"]
|
|
187
|
+
|
|
188
|
+
puts "Retrieved #{items.length} items"
|
|
189
|
+
puts "Next cursor: #{cursor}"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Handling Missing Data
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
response = client.board.query(args: { ids: [999] })
|
|
196
|
+
|
|
197
|
+
boards = response.body.dig("data", "boards")
|
|
198
|
+
|
|
199
|
+
if boards.nil? || boards.empty?
|
|
200
|
+
puts "No boards found"
|
|
201
|
+
else
|
|
202
|
+
puts "Found #{boards.length} boards"
|
|
203
|
+
end
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Error Responses
|
|
207
|
+
|
|
208
|
+
### Checking for Errors
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
response = client.board.query(args: { ids: [123] })
|
|
212
|
+
|
|
213
|
+
unless response.success?
|
|
214
|
+
if response.body["errors"]
|
|
215
|
+
errors = response.body["errors"]
|
|
216
|
+
errors.each do |error|
|
|
217
|
+
puts "Error: #{error['message']}"
|
|
218
|
+
end
|
|
219
|
+
elsif response.body["error_message"]
|
|
220
|
+
puts "Error: #{response.body['error_message']}"
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Error Response Examples
|
|
226
|
+
|
|
227
|
+
**Authorization Error (HTTP 200 with errors in body):**
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
{
|
|
231
|
+
"errors" => [
|
|
232
|
+
{
|
|
233
|
+
"message" => "User unauthorized to perform action",
|
|
234
|
+
"extensions" => {
|
|
235
|
+
"code" => "AuthorizationException"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
"account_id" => 12345678
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
response.status # => 200
|
|
243
|
+
response.success? # => false (because errors key exists)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Invalid Token (HTTP 401):**
|
|
247
|
+
|
|
248
|
+
```ruby
|
|
249
|
+
{
|
|
250
|
+
"error_message" => "Invalid token",
|
|
251
|
+
"error_code" => "InvalidTokenException"
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
response.status # => 401
|
|
255
|
+
response.success? # => false
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Rate Limit (HTTP 429):**
|
|
259
|
+
|
|
260
|
+
```ruby
|
|
261
|
+
{
|
|
262
|
+
"error_message" => "You have reached the rate limit",
|
|
263
|
+
"error_code" => "ComplexityException"
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
response.status # => 429
|
|
267
|
+
response.success? # => false
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Invalid Query (HTTP 200 with errors in body):**
|
|
271
|
+
|
|
272
|
+
```ruby
|
|
273
|
+
{
|
|
274
|
+
"errors" => [
|
|
275
|
+
{
|
|
276
|
+
"message" => "Field 'invalid_field' doesn't exist on type 'Board'",
|
|
277
|
+
"locations" => [{ "line" => 1, "column" => 20 }]
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
response.status # => 200
|
|
283
|
+
response.success? # => false (because errors key exists)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Usage Examples
|
|
287
|
+
|
|
288
|
+
### Basic Query
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
response = client.board.query(args: { ids: [123] })
|
|
292
|
+
|
|
293
|
+
if response.success?
|
|
294
|
+
boards = response.body.dig("data", "boards")
|
|
295
|
+
puts "Found #{boards.length} boards"
|
|
296
|
+
else
|
|
297
|
+
puts "Request failed with status #{response.status}"
|
|
298
|
+
end
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Create Operation
|
|
302
|
+
|
|
303
|
+
```ruby
|
|
304
|
+
response = client.board.create(
|
|
305
|
+
args: {
|
|
306
|
+
board_name: "New Board",
|
|
307
|
+
board_kind: :public
|
|
308
|
+
}
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
if response.success?
|
|
312
|
+
board = response.body.dig("data", "create_board")
|
|
313
|
+
puts "Created board #{board['id']}: #{board['name']}"
|
|
314
|
+
else
|
|
315
|
+
errors = response.body["errors"]
|
|
316
|
+
puts "Failed to create board: #{errors}"
|
|
317
|
+
end
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Handling Nested Data
|
|
321
|
+
|
|
322
|
+
```ruby
|
|
323
|
+
response = client.item.query(
|
|
324
|
+
args: { ids: [456] },
|
|
325
|
+
select: ["id", "name", { column_values: ["id", "text", "value"] }]
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
if response.success?
|
|
329
|
+
items = response.body.dig("data", "items")
|
|
330
|
+
item = items&.first
|
|
331
|
+
|
|
332
|
+
if item
|
|
333
|
+
puts "Item: #{item['name']}"
|
|
334
|
+
|
|
335
|
+
column_values = item["column_values"]
|
|
336
|
+
column_values&.each do |cv|
|
|
337
|
+
puts " #{cv['id']}: #{cv['text']}"
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Checking Response Headers
|
|
344
|
+
|
|
345
|
+
```ruby
|
|
346
|
+
response = client.board.query(args: { ids: [123] })
|
|
347
|
+
|
|
348
|
+
puts "Status: #{response.status}"
|
|
349
|
+
puts "Content-Type: #{response.headers['content-type']}"
|
|
350
|
+
puts "Rate Limit: #{response.headers['x-ratelimit-remaining']}"
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Processing Multiple Results
|
|
354
|
+
|
|
355
|
+
```ruby
|
|
356
|
+
response = client.board.query(
|
|
357
|
+
args: { ids: [123, 456, 789] }
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
if response.success?
|
|
361
|
+
boards = response.body.dig("data", "boards") || []
|
|
362
|
+
|
|
363
|
+
boards.each do |board|
|
|
364
|
+
puts "Board #{board['id']}: #{board['name']}"
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
puts "\nTotal: #{boards.length} boards"
|
|
368
|
+
else
|
|
369
|
+
puts "Failed to fetch boards"
|
|
370
|
+
end
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Best Practices
|
|
374
|
+
|
|
375
|
+
### Always Check success?
|
|
376
|
+
|
|
377
|
+
Never assume a request succeeded. Always check before accessing data:
|
|
378
|
+
|
|
379
|
+
```ruby
|
|
380
|
+
# Good
|
|
381
|
+
response = client.board.query(args: { ids: [123] })
|
|
382
|
+
|
|
383
|
+
if response.success?
|
|
384
|
+
boards = response.body.dig("data", "boards")
|
|
385
|
+
# Work with boards
|
|
386
|
+
else
|
|
387
|
+
# Handle error
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# Bad - will raise error if request fails
|
|
391
|
+
boards = client.board.query(args: { ids: [123] }).body["data"]["boards"]
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Use dig for Safe Navigation
|
|
395
|
+
|
|
396
|
+
Use `dig` to safely access nested data:
|
|
397
|
+
|
|
398
|
+
```ruby
|
|
399
|
+
# Good - returns nil if any key is missing
|
|
400
|
+
board = response.body.dig("data", "boards", 0)
|
|
401
|
+
name = board&.dig("name")
|
|
402
|
+
|
|
403
|
+
# Bad - raises error if key is missing
|
|
404
|
+
name = response.body["data"]["boards"][0]["name"]
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Handle nil Results
|
|
408
|
+
|
|
409
|
+
Always check for nil before iterating:
|
|
410
|
+
|
|
411
|
+
```ruby
|
|
412
|
+
# Good
|
|
413
|
+
boards = response.body.dig("data", "boards") || []
|
|
414
|
+
boards.each { |board| puts board["name"] }
|
|
415
|
+
|
|
416
|
+
# Or
|
|
417
|
+
boards = response.body.dig("data", "boards")
|
|
418
|
+
if boards
|
|
419
|
+
boards.each { |board| puts board["name"] }
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Bad - raises error if boards is nil
|
|
423
|
+
boards = response.body.dig("data", "boards")
|
|
424
|
+
boards.each { |board| puts board["name"] }
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Store Response Data
|
|
428
|
+
|
|
429
|
+
Extract data from the response before working with it:
|
|
430
|
+
|
|
431
|
+
```ruby
|
|
432
|
+
# Good
|
|
433
|
+
response = client.board.query(args: { ids: [123] })
|
|
434
|
+
|
|
435
|
+
if response.success?
|
|
436
|
+
boards = response.body.dig("data", "boards")
|
|
437
|
+
# Now work with boards array
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# Less efficient - accessing response.body multiple times
|
|
441
|
+
if response.success?
|
|
442
|
+
response.body.dig("data", "boards").each do |board|
|
|
443
|
+
# ...
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Check Both success? and Data Presence
|
|
449
|
+
|
|
450
|
+
Some queries may succeed but return empty results:
|
|
451
|
+
|
|
452
|
+
```ruby
|
|
453
|
+
response = client.board.query(args: { ids: [999] })
|
|
454
|
+
|
|
455
|
+
if response.success?
|
|
456
|
+
boards = response.body.dig("data", "boards")
|
|
457
|
+
|
|
458
|
+
if boards && !boards.empty?
|
|
459
|
+
# Process boards
|
|
460
|
+
else
|
|
461
|
+
puts "No boards found with ID 999"
|
|
462
|
+
end
|
|
463
|
+
else
|
|
464
|
+
puts "Request failed: #{response.status}"
|
|
465
|
+
end
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## GraphQL Response Format
|
|
469
|
+
|
|
470
|
+
### Data Wrapper
|
|
471
|
+
|
|
472
|
+
All successful GraphQL responses wrap data in a `"data"` key:
|
|
473
|
+
|
|
474
|
+
```ruby
|
|
475
|
+
{
|
|
476
|
+
"data" => {
|
|
477
|
+
# Actual response data here
|
|
478
|
+
},
|
|
479
|
+
"account_id" => 12345678
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Query Responses
|
|
484
|
+
|
|
485
|
+
Query responses use plural resource names:
|
|
486
|
+
|
|
487
|
+
```ruby
|
|
488
|
+
# boards query
|
|
489
|
+
{
|
|
490
|
+
"data" => {
|
|
491
|
+
"boards" => [...]
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
# items query
|
|
496
|
+
{
|
|
497
|
+
"data" => {
|
|
498
|
+
"items" => [...]
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Mutation Responses
|
|
504
|
+
|
|
505
|
+
Mutation responses use the mutation name:
|
|
506
|
+
|
|
507
|
+
```ruby
|
|
508
|
+
# create_board
|
|
509
|
+
{
|
|
510
|
+
"data" => {
|
|
511
|
+
"create_board" => { "id" => "123", "name" => "New Board" }
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
# update_board (returns JSON string)
|
|
516
|
+
{
|
|
517
|
+
"data" => {
|
|
518
|
+
"update_board" => '{"success":true,"undo_data":"..."}'
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
# duplicate_board (nested under "board")
|
|
523
|
+
{
|
|
524
|
+
"data" => {
|
|
525
|
+
"duplicate_board" => {
|
|
526
|
+
"board" => { "id" => "456", "name" => "Duplicated Board" }
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Error Structure
|
|
533
|
+
|
|
534
|
+
Errors use the `"errors"` array:
|
|
535
|
+
|
|
536
|
+
```ruby
|
|
537
|
+
{
|
|
538
|
+
"errors" => [
|
|
539
|
+
{
|
|
540
|
+
"message" => "Error description",
|
|
541
|
+
"extensions" => {
|
|
542
|
+
"code" => "ErrorCode"
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
],
|
|
546
|
+
"account_id" => 12345678
|
|
547
|
+
}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
## Related Documentation
|
|
551
|
+
|
|
552
|
+
- [Client](/reference/client) - Making API requests
|
|
553
|
+
- [Error Handling](/guides/advanced/errors) - Handling exceptions
|
|
554
|
+
- [Board Resource](/reference/resources/board) - Example resource usage
|
|
555
|
+
- [Item Resource](/reference/resources/item) - Example resource usage
|
|
556
|
+
|
|
557
|
+
## External References
|
|
558
|
+
|
|
559
|
+
- [monday.com GraphQL API](https://developer.monday.com/api-reference/docs/introduction-to-graphql)
|
|
560
|
+
- [GraphQL Response Format](https://graphql.org/learn/serving-over-http/)
|