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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.env +1 -1
  3. data/.rspec +0 -1
  4. data/.rubocop.yml +19 -0
  5. data/.simplecov +1 -0
  6. data/CHANGELOG.md +49 -0
  7. data/CONTRIBUTING.md +165 -0
  8. data/README.md +167 -88
  9. data/docs/.vitepress/config.mjs +255 -0
  10. data/docs/.vitepress/theme/index.js +4 -0
  11. data/docs/.vitepress/theme/style.css +43 -0
  12. data/docs/README.md +80 -0
  13. data/docs/explanation/architecture.md +507 -0
  14. data/docs/explanation/best-practices/errors.md +478 -0
  15. data/docs/explanation/best-practices/performance.md +1084 -0
  16. data/docs/explanation/best-practices/rate-limiting.md +630 -0
  17. data/docs/explanation/best-practices/testing.md +820 -0
  18. data/docs/explanation/column-values.md +857 -0
  19. data/docs/explanation/design.md +795 -0
  20. data/docs/explanation/graphql.md +356 -0
  21. data/docs/explanation/migration/v1.md +808 -0
  22. data/docs/explanation/pagination.md +447 -0
  23. data/docs/guides/advanced/batch.md +1274 -0
  24. data/docs/guides/advanced/complex-queries.md +1114 -0
  25. data/docs/guides/advanced/errors.md +818 -0
  26. data/docs/guides/advanced/pagination.md +934 -0
  27. data/docs/guides/advanced/rate-limiting.md +981 -0
  28. data/docs/guides/authentication.md +286 -0
  29. data/docs/guides/boards/create.md +386 -0
  30. data/docs/guides/boards/delete.md +405 -0
  31. data/docs/guides/boards/duplicate.md +511 -0
  32. data/docs/guides/boards/query.md +530 -0
  33. data/docs/guides/boards/update.md +453 -0
  34. data/docs/guides/columns/create.md +452 -0
  35. data/docs/guides/columns/metadata.md +492 -0
  36. data/docs/guides/columns/query.md +455 -0
  37. data/docs/guides/columns/update-multiple.md +459 -0
  38. data/docs/guides/columns/update-values.md +509 -0
  39. data/docs/guides/files/add-to-column.md +40 -0
  40. data/docs/guides/files/add-to-update.md +37 -0
  41. data/docs/guides/files/clear-column.md +33 -0
  42. data/docs/guides/first-request.md +285 -0
  43. data/docs/guides/folders/manage.md +750 -0
  44. data/docs/guides/groups/items.md +626 -0
  45. data/docs/guides/groups/manage.md +501 -0
  46. data/docs/guides/installation.md +169 -0
  47. data/docs/guides/items/create.md +493 -0
  48. data/docs/guides/items/delete.md +514 -0
  49. data/docs/guides/items/query.md +605 -0
  50. data/docs/guides/items/subitems.md +483 -0
  51. data/docs/guides/items/update.md +699 -0
  52. data/docs/guides/updates/manage.md +619 -0
  53. data/docs/guides/use-cases/dashboard.md +1421 -0
  54. data/docs/guides/use-cases/import.md +1962 -0
  55. data/docs/guides/use-cases/task-management.md +1381 -0
  56. data/docs/guides/workspaces/manage.md +502 -0
  57. data/docs/index.md +69 -0
  58. data/docs/package-lock.json +2468 -0
  59. data/docs/package.json +13 -0
  60. data/docs/reference/client.md +540 -0
  61. data/docs/reference/configuration.md +586 -0
  62. data/docs/reference/errors.md +693 -0
  63. data/docs/reference/resources/account.md +208 -0
  64. data/docs/reference/resources/activity-log.md +369 -0
  65. data/docs/reference/resources/board-view.md +359 -0
  66. data/docs/reference/resources/board.md +393 -0
  67. data/docs/reference/resources/column.md +543 -0
  68. data/docs/reference/resources/file.md +236 -0
  69. data/docs/reference/resources/folder.md +386 -0
  70. data/docs/reference/resources/group.md +507 -0
  71. data/docs/reference/resources/item.md +348 -0
  72. data/docs/reference/resources/subitem.md +267 -0
  73. data/docs/reference/resources/update.md +259 -0
  74. data/docs/reference/resources/workspace.md +213 -0
  75. data/docs/reference/response.md +560 -0
  76. data/docs/tutorial/first-integration.md +713 -0
  77. data/lib/monday/client.rb +41 -2
  78. data/lib/monday/configuration.rb +13 -0
  79. data/lib/monday/deprecation.rb +23 -0
  80. data/lib/monday/error.rb +5 -2
  81. data/lib/monday/request.rb +19 -1
  82. data/lib/monday/resources/base.rb +4 -0
  83. data/lib/monday/resources/board.rb +52 -0
  84. data/lib/monday/resources/column.rb +6 -0
  85. data/lib/monday/resources/file.rb +56 -0
  86. data/lib/monday/resources/folder.rb +55 -0
  87. data/lib/monday/resources/group.rb +66 -0
  88. data/lib/monday/resources/item.rb +62 -0
  89. data/lib/monday/util.rb +33 -1
  90. data/lib/monday/version.rb +1 -1
  91. data/lib/monday_ruby.rb +1 -0
  92. metadata +92 -11
  93. data/monday_ruby.gemspec +0 -39
@@ -0,0 +1,626 @@
1
+ # Work with Items in Groups
2
+
3
+ Learn how to move items between groups and retrieve paginated items from groups efficiently.
4
+
5
+ ## Move Items Between Groups
6
+
7
+ Reorganize items by moving them to different groups on the same board.
8
+
9
+ ### Basic Item Move
10
+
11
+ Move an item to a different group:
12
+
13
+ ```ruby
14
+ require "monday_ruby"
15
+
16
+ Monday.configure do |config|
17
+ config.token = ENV["MONDAY_TOKEN"]
18
+ end
19
+
20
+ client = Monday::Client.new
21
+
22
+ response = client.group.move_item(
23
+ args: {
24
+ item_id: 987654321,
25
+ group_id: "group_mkx1yn2n"
26
+ }
27
+ )
28
+
29
+ if response.success?
30
+ item = response.body.dig("data", "move_item_to_group")
31
+ puts "✓ Moved item #{item['id']} to new group"
32
+ end
33
+ ```
34
+
35
+ ### Move with Group Information
36
+
37
+ Confirm the new group after moving:
38
+
39
+ ```ruby
40
+ response = client.group.move_item(
41
+ args: {
42
+ item_id: 987654321,
43
+ group_id: "group_mkx1yn2n"
44
+ },
45
+ select: [
46
+ "id",
47
+ "name",
48
+ {
49
+ group: ["id", "title"]
50
+ }
51
+ ]
52
+ )
53
+
54
+ if response.success?
55
+ item = response.body.dig("data", "move_item_to_group")
56
+ group = item["group"]
57
+
58
+ puts "✓ Item: #{item['name']}"
59
+ puts " Moved to: #{group['title']} (#{group['id']})"
60
+ end
61
+ ```
62
+
63
+ **Output:**
64
+ ```
65
+ ✓ Item: Order #1234
66
+ Moved to: Completed Orders (group_mkx1yn2n)
67
+ ```
68
+
69
+ ### Move Multiple Items
70
+
71
+ Batch move items to a group:
72
+
73
+ ```ruby
74
+ item_ids = [111, 222, 333, 444, 555]
75
+ destination_group = "group_mkx1yn2n"
76
+
77
+ puts "Moving #{item_ids.length} items..."
78
+
79
+ item_ids.each do |item_id|
80
+ response = client.group.move_item(
81
+ args: {
82
+ item_id: item_id,
83
+ group_id: destination_group
84
+ }
85
+ )
86
+
87
+ if response.success?
88
+ puts "✓ Moved item #{item_id}"
89
+ else
90
+ puts "✗ Failed to move item #{item_id}"
91
+ end
92
+ end
93
+
94
+ puts "Complete!"
95
+ ```
96
+
97
+ ### Organize Items by Status
98
+
99
+ Move items based on their status:
100
+
101
+ ```ruby
102
+ # Get items from board
103
+ board_response = client.board.items_page(
104
+ board_ids: 123,
105
+ limit: 100,
106
+ select: [
107
+ "id",
108
+ "name",
109
+ {
110
+ column_values: ["id", "text"]
111
+ }
112
+ ]
113
+ )
114
+
115
+ items = board_response.body.dig("data", "boards", 0, "items_page", "items")
116
+
117
+ # Move completed items to "Done" group
118
+ done_group_id = "group_done123"
119
+
120
+ items.each do |item|
121
+ status_column = item["column_values"].find { |cv| cv["id"] == "status" }
122
+
123
+ if status_column && status_column["text"] == "Done"
124
+ response = client.group.move_item(
125
+ args: {
126
+ item_id: item["id"],
127
+ group_id: done_group_id
128
+ }
129
+ )
130
+
131
+ puts "✓ Moved #{item['name']} to Done group" if response.success?
132
+ end
133
+ end
134
+ ```
135
+
136
+ ## Paginated Item Retrieval
137
+
138
+ Efficiently retrieve large numbers of items from groups using cursor-based pagination.
139
+
140
+ ### Basic Pagination
141
+
142
+ Retrieve first page of items:
143
+
144
+ ```ruby
145
+ response = client.group.items_page(
146
+ board_ids: 123,
147
+ group_ids: "group_mkx1yn2n",
148
+ limit: 50
149
+ )
150
+
151
+ if response.success?
152
+ items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
153
+ items = items_page["items"]
154
+ cursor = items_page["cursor"]
155
+
156
+ puts "Retrieved #{items.length} items"
157
+ puts "More pages available: #{!cursor.nil?}"
158
+ end
159
+ ```
160
+
161
+ **Output:**
162
+ ```
163
+ Retrieved 50 items
164
+ More pages available: true
165
+ ```
166
+
167
+ ### Fetch All Pages
168
+
169
+ Loop through all pages using cursors:
170
+
171
+ ```ruby
172
+ board_id = 123
173
+ group_id = "group_mkx1yn2n"
174
+ all_items = []
175
+ cursor = nil
176
+
177
+ loop do
178
+ response = client.group.items_page(
179
+ board_ids: board_id,
180
+ group_ids: group_id,
181
+ limit: 100,
182
+ cursor: cursor
183
+ )
184
+
185
+ items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
186
+ items = items_page["items"]
187
+ cursor = items_page["cursor"]
188
+
189
+ all_items.concat(items)
190
+ puts "Fetched #{items.length} items (total: #{all_items.length})"
191
+
192
+ break if cursor.nil? # No more pages
193
+ end
194
+
195
+ puts "\n✓ Retrieved all #{all_items.length} items"
196
+ ```
197
+
198
+ **Output:**
199
+ ```
200
+ Fetched 100 items (total: 100)
201
+ Fetched 100 items (total: 200)
202
+ Fetched 47 items (total: 247)
203
+
204
+ ✓ Retrieved all 247 items
205
+ ```
206
+
207
+ ### Multiple Groups
208
+
209
+ Retrieve items from multiple groups:
210
+
211
+ ```ruby
212
+ response = client.group.items_page(
213
+ board_ids: 123,
214
+ group_ids: ["group_1", "group_2", "group_3"],
215
+ limit: 50
216
+ )
217
+
218
+ if response.success?
219
+ boards = response.body.dig("data", "boards")
220
+
221
+ boards.each do |board|
222
+ board["groups"].each do |group|
223
+ items = group["items_page"]["items"]
224
+ cursor = group["items_page"]["cursor"]
225
+
226
+ puts "Group has #{items.length} items"
227
+ puts "More pages: #{!cursor.nil?}"
228
+ end
229
+ end
230
+ end
231
+ ```
232
+
233
+ ### Multiple Boards and Groups
234
+
235
+ Query across multiple boards:
236
+
237
+ ```ruby
238
+ response = client.group.items_page(
239
+ board_ids: [123, 456],
240
+ group_ids: ["group_mkx1yn2n", "group_abc123"],
241
+ limit: 100
242
+ )
243
+
244
+ boards = response.body.dig("data", "boards")
245
+
246
+ boards.each_with_index do |board, board_index|
247
+ board["groups"].each_with_index do |group, group_index|
248
+ items = group["items_page"]["items"]
249
+ puts "Board #{board_index + 1}, Group #{group_index + 1}: #{items.length} items"
250
+ end
251
+ end
252
+ ```
253
+
254
+ ## Filter Items with Query Params
255
+
256
+ Retrieve only items matching specific criteria.
257
+
258
+ ### Filter by Column Value
259
+
260
+ Get items with specific status:
261
+
262
+ ```ruby
263
+ response = client.group.items_page(
264
+ board_ids: 123,
265
+ group_ids: "group_mkx1yn2n",
266
+ limit: 100,
267
+ query_params: {
268
+ rules: [
269
+ { column_id: "status", compare_value: [1] } # Status index 1
270
+ ],
271
+ operator: :and
272
+ }
273
+ )
274
+
275
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
276
+ puts "Found #{items.length} items with selected status"
277
+ ```
278
+
279
+ ### Multiple Filter Rules
280
+
281
+ Combine multiple conditions:
282
+
283
+ ```ruby
284
+ response = client.group.items_page(
285
+ board_ids: 123,
286
+ group_ids: "group_mkx1yn2n",
287
+ limit: 100,
288
+ query_params: {
289
+ rules: [
290
+ { column_id: "status", compare_value: [1, 2] }, # Status 1 or 2
291
+ { column_id: "priority", compare_value: [0] } # High priority
292
+ ],
293
+ operator: :and # Items must match ALL rules
294
+ }
295
+ )
296
+
297
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
298
+ puts "Found #{items.length} high-priority items in progress"
299
+ ```
300
+
301
+ ### Filter with OR Operator
302
+
303
+ Match items meeting any condition:
304
+
305
+ ```ruby
306
+ response = client.group.items_page(
307
+ board_ids: 123,
308
+ group_ids: "group_mkx1yn2n",
309
+ limit: 100,
310
+ query_params: {
311
+ rules: [
312
+ { column_id: "status", compare_value: [0] }, # Not started
313
+ { column_id: "status", compare_value: [5] } # Stuck
314
+ ],
315
+ operator: :or # Items matching ANY rule
316
+ }
317
+ )
318
+
319
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
320
+ puts "Found #{items.length} items needing attention"
321
+ ```
322
+
323
+ ### Filter by Text Column
324
+
325
+ Search by item name or text column:
326
+
327
+ ```ruby
328
+ response = client.group.items_page(
329
+ board_ids: 123,
330
+ group_ids: "group_mkx1yn2n",
331
+ limit: 100,
332
+ query_params: {
333
+ rules: [
334
+ { column_id: "name", compare_value: ["Test Item 1"] }
335
+ ],
336
+ operator: :and
337
+ }
338
+ )
339
+
340
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
341
+ items.each do |item|
342
+ puts "• #{item['name']}"
343
+ end
344
+ ```
345
+
346
+ ## Custom Field Selection
347
+
348
+ Retrieve specific fields to reduce response size and improve performance.
349
+
350
+ ### Basic Fields
351
+
352
+ Get essential item information:
353
+
354
+ ```ruby
355
+ response = client.group.items_page(
356
+ board_ids: 123,
357
+ group_ids: "group_mkx1yn2n",
358
+ limit: 50,
359
+ select: ["id", "name", "created_at", "updated_at"]
360
+ )
361
+
362
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
363
+
364
+ items.each do |item|
365
+ puts "#{item['name']} (created: #{item['created_at']})"
366
+ end
367
+ ```
368
+
369
+ ### Include Column Values
370
+
371
+ Get item data with column values:
372
+
373
+ ```ruby
374
+ response = client.group.items_page(
375
+ board_ids: 123,
376
+ group_ids: "group_mkx1yn2n",
377
+ limit: 50,
378
+ select: [
379
+ "id",
380
+ "name",
381
+ {
382
+ column_values: ["id", "text", "value"]
383
+ }
384
+ ]
385
+ )
386
+
387
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
388
+
389
+ items.each do |item|
390
+ puts "\nItem: #{item['name']}"
391
+ item["column_values"].each do |cv|
392
+ puts " #{cv['id']}: #{cv['text']}"
393
+ end
394
+ end
395
+ ```
396
+
397
+ **Output:**
398
+ ```
399
+ Item: Order #1234
400
+ status: In Progress
401
+ person: John Doe
402
+ date: 2024-01-15
403
+
404
+ Item: Order #1235
405
+ status: Done
406
+ person: Jane Smith
407
+ date: 2024-01-16
408
+ ```
409
+
410
+ ### Include Related Objects
411
+
412
+ Get group and board information with items:
413
+
414
+ ```ruby
415
+ response = client.group.items_page(
416
+ board_ids: 123,
417
+ group_ids: "group_mkx1yn2n",
418
+ limit: 50,
419
+ select: [
420
+ "id",
421
+ "name",
422
+ {
423
+ group: ["id", "title", "color"]
424
+ },
425
+ {
426
+ board: ["id", "name"]
427
+ }
428
+ ]
429
+ )
430
+
431
+ items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
432
+
433
+ items.each do |item|
434
+ puts "#{item['name']} in #{item['group']['title']} on #{item['board']['name']}"
435
+ end
436
+ ```
437
+
438
+ ## Cursor Expiration
439
+
440
+ Cursors expire after 60 minutes. Handle expired cursors gracefully:
441
+
442
+ ```ruby
443
+ def fetch_all_items(client, board_id, group_id)
444
+ all_items = []
445
+ cursor = nil
446
+ max_retries = 3
447
+ retry_count = 0
448
+
449
+ loop do
450
+ begin
451
+ response = client.group.items_page(
452
+ board_ids: board_id,
453
+ group_ids: group_id,
454
+ limit: 100,
455
+ cursor: cursor
456
+ )
457
+
458
+ items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
459
+ items = items_page["items"]
460
+ cursor = items_page["cursor"]
461
+
462
+ all_items.concat(items)
463
+ puts "Fetched #{items.length} items"
464
+
465
+ retry_count = 0 # Reset on success
466
+ break if cursor.nil?
467
+
468
+ rescue Monday::Error => e
469
+ retry_count += 1
470
+
471
+ if retry_count <= max_retries
472
+ puts "Error: #{e.message}. Retrying from start..."
473
+ cursor = nil # Start over
474
+ all_items = []
475
+ else
476
+ puts "Max retries reached. Failed to fetch all items."
477
+ raise
478
+ end
479
+ end
480
+ end
481
+
482
+ all_items
483
+ end
484
+
485
+ # Usage
486
+ items = fetch_all_items(client, 123, "group_mkx1yn2n")
487
+ puts "Total items: #{items.length}"
488
+ ```
489
+
490
+ ## Performance Tips
491
+
492
+ Optimize pagination for better performance:
493
+
494
+ ### Use Appropriate Page Sizes
495
+
496
+ ```ruby
497
+ # For quick scans - smaller pages
498
+ response = client.group.items_page(
499
+ board_ids: 123,
500
+ group_ids: "group_mkx1yn2n",
501
+ limit: 25 # Faster initial response
502
+ )
503
+
504
+ # For bulk processing - larger pages
505
+ response = client.group.items_page(
506
+ board_ids: 123,
507
+ group_ids: "group_mkx1yn2n",
508
+ limit: 500 # Maximum, fewer requests
509
+ )
510
+ ```
511
+
512
+ ### Request Only Needed Fields
513
+
514
+ ```ruby
515
+ # Good - only necessary fields
516
+ response = client.group.items_page(
517
+ board_ids: 123,
518
+ group_ids: "group_mkx1yn2n",
519
+ limit: 100,
520
+ select: ["id", "name"] # Minimal payload
521
+ )
522
+
523
+ # Avoid - requesting everything
524
+ response = client.group.items_page(
525
+ board_ids: 123,
526
+ group_ids: "group_mkx1yn2n",
527
+ limit: 100,
528
+ select: [
529
+ "id", "name", "created_at", "updated_at", "creator_id", "state",
530
+ { column_values: ["id", "text", "value", "additional_info"] },
531
+ { board: ["id", "name", "description", "state", "board_kind"] }
532
+ ] # Large payload, slower
533
+ )
534
+ ```
535
+
536
+ ## Complete Example
537
+
538
+ Full workflow for working with group items:
539
+
540
+ ```ruby
541
+ require "monday_ruby"
542
+ require "dotenv/load"
543
+
544
+ Monday.configure do |config|
545
+ config.token = ENV["MONDAY_TOKEN"]
546
+ end
547
+
548
+ client = Monday::Client.new
549
+
550
+ board_id = 123
551
+ in_progress_group = "group_progress"
552
+ done_group = "group_done"
553
+
554
+ # 1. Get all items from "In Progress" group
555
+ puts "=== Fetching In Progress Items ==="
556
+ all_items = []
557
+ cursor = nil
558
+
559
+ loop do
560
+ response = client.group.items_page(
561
+ board_ids: board_id,
562
+ group_ids: in_progress_group,
563
+ limit: 100,
564
+ cursor: cursor,
565
+ select: [
566
+ "id",
567
+ "name",
568
+ { column_values: ["id", "text"] }
569
+ ]
570
+ )
571
+
572
+ items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
573
+ items = items_page["items"]
574
+ cursor = items_page["cursor"]
575
+
576
+ all_items.concat(items)
577
+ break if cursor.nil?
578
+ end
579
+
580
+ puts "Found #{all_items.length} items in progress"
581
+
582
+ # 2. Identify completed items
583
+ completed_items = all_items.select do |item|
584
+ status = item["column_values"].find { |cv| cv["id"] == "status" }
585
+ status && status["text"] == "Done"
586
+ end
587
+
588
+ puts "\n=== Moving Completed Items ==="
589
+ puts "#{completed_items.length} items are done"
590
+
591
+ # 3. Move completed items to Done group
592
+ completed_items.each do |item|
593
+ response = client.group.move_item(
594
+ args: {
595
+ item_id: item["id"],
596
+ group_id: done_group
597
+ }
598
+ )
599
+
600
+ if response.success?
601
+ puts "✓ Moved: #{item['name']}"
602
+ else
603
+ puts "✗ Failed: #{item['name']}"
604
+ end
605
+ end
606
+
607
+ # 4. Verify Done group
608
+ puts "\n=== Verifying Done Group ==="
609
+ response = client.group.items_page(
610
+ board_ids: board_id,
611
+ group_ids: done_group,
612
+ limit: 100
613
+ )
614
+
615
+ done_items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
616
+ puts "Done group now has #{done_items.length} items"
617
+
618
+ puts "\n=== Complete ==="
619
+ ```
620
+
621
+ ## Next Steps
622
+
623
+ - [Manage groups](/guides/groups/manage)
624
+ - [Create items](/guides/items/create)
625
+ - [Update item values](/guides/columns/update-values)
626
+ - [Query items](/guides/items/query)