monday_ruby 0.2.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e17b85396d9acd3d8dc9346a1c1b54f09280d8815941deee3ed952de6cf55ad1
4
- data.tar.gz: 2bc9f14384736558a423f8690175a49dcf716746a2db1f5a5ef51cd7fefb0532
3
+ metadata.gz: 6f0e71a61ef39a418ca03c8151a357e3623f9c4a030c74cee613e4cefc8d684a
4
+ data.tar.gz: 2ab39c2856f63b1e72a9395630c43b92fd589b1790954b36791ed105f6e52362
5
5
  SHA512:
6
- metadata.gz: d594d0addabe0adbb550ecf474e12c4d7645e10bdf37a9fe10c7b930ab63d954204c1658f30dd6258303c2b7c1e8fb6ace0476beb23fbf91fc864f9dfb4f6fe4
7
- data.tar.gz: e42cdc2c6bcf6de3d5652e5bfa9c3d86f377155f0c2e06e76c2857b691341eca3e115e6abc8811fa02976afcda4997f8f3feffbc3f16b058bf4f3b9849c69835
6
+ metadata.gz: 65ad4b3eec9937e42fe5a2a811f7ccdc2caf3c17e4b38ede2b10a7be148519ec6a7e75d5b272fb86c33667be7309b2c51858f7e97563f147ca1f35d9adca1ac9
7
+ data.tar.gz: 41c14a6bd4c846d25701a19a7dadb775e379ac2a45b1967b3d97025301dfb1ccdbc5983c4efa6d78769f9daedfb9d3a9773fa976140816017d97308f128b4814
data/.rubocop.yml CHANGED
@@ -16,3 +16,7 @@ Layout/LineLength:
16
16
  Metrics/BlockLength:
17
17
  Exclude:
18
18
  - "spec/**/*_spec.rb"
19
+
20
+ Metrics/MethodLength:
21
+ Exclude:
22
+ - "lib/monday/util.rb"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## v0.4.0 (September 15, 2023)
2
+
3
+ ### Added
4
+
5
+ - Support for Reading, Creating and Deleting Workspaces
6
+
7
+ ## v0.3.0 (July 10, 2023)
8
+
9
+ ### Added
10
+
11
+ - Improved error handling
12
+ - Support to configure the API version
13
+ - Coverage report
14
+
1
15
  ## v0.2.0 (July 04, 2023)
2
16
 
3
17
  ### Added
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,25 @@
1
+ # Contributing
2
+
3
+ Thanks for taking the time to contribute!
4
+
5
+ The following is a set of guidelines for contributing to `monday_ruby`. These are mostly guidelines, not rules. Use your best judgment, and feel to propose changes to this document in a pull request.
6
+
7
+ ## Your first code contribution
8
+
9
+ Unsure where to begin contributing? You can start by looking through `good first issue` and `help wanted` issues.
10
+
11
+ ### Pull request
12
+
13
+ Please follow these steps to have your contribution considered:
14
+
15
+ 1. Follow the [pull request template](PULL_REQUEST_TEMPLATE.md).
16
+ 2. Follow the [commit guidelines](#commit-message-guidelines).
17
+ 3. After you submit your pull request, verify that all the status checks are passing.
18
+
19
+ ## Commit message guidelines
20
+
21
+ * Use present tense ("Add feature" not "Added feature")
22
+ * Use the imperative mood ("Move file to..." not "Moves file to...")
23
+ * Limit the first line to 70 characters or less.
24
+ * Reference issues and pull requests after the first line.
25
+ * Try to follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ![Build Status](https://github.com/sanifhimani/monday_ruby/actions/workflows/ci.yml/badge.svg)
4
4
  [![Gem Version](https://badge.fury.io/rb/monday_ruby.svg)](https://badge.fury.io/rb/monday_ruby)
5
+ [![Coverage Status](https://coveralls.io/repos/github/sanifhimani/monday_ruby/badge.svg?branch=main)](https://coveralls.io/github/sanifhimani/monday_ruby?branch=main)
5
6
 
6
7
  This library provides convenient access to the monday.com API from the application written in the Ruby language.
7
8
 
@@ -9,6 +10,7 @@ The library provides:
9
10
 
10
11
  1. A pre-defined set of methods to easily interact with the API resources.
11
12
  2. Easy configuration path for fast setup and use.
13
+ 3. Easy error handling.
12
14
 
13
15
  **Visit https://monday-ruby.gitbook.io/docs/ for detailed documentation on how to use the library.**
14
16
 
@@ -68,6 +70,17 @@ require "monday_ruby"
68
70
  client = Monday::Client.new(token: "<AUTH_TOKEN>")
69
71
  ```
70
72
 
73
+ You can optionally pass in the version of the API you want to use using the version configuration field. By default, the latest stable version is used.
74
+
75
+ ```ruby
76
+ require "monday_ruby"
77
+
78
+ Monday.configure do |config|
79
+ config.token = "<AUTH_TOKEN>"
80
+ config.version = "2023-07"
81
+ end
82
+ ```
83
+
71
84
  ### Accessing a response object
72
85
 
73
86
  Get access to response objects by initializing a client and using the appropriate action you want to perform:
data/docs/README.md CHANGED
@@ -6,6 +6,7 @@ The library provides:
6
6
 
7
7
  1. A pre-defined set of methods to easily interact with the API resources.
8
8
  2. Easy configuration path for fast setup and use.
9
+ 3. Easy error handling
9
10
 
10
11
  #### Requirements
11
12
 
data/docs/SUMMARY.md CHANGED
@@ -6,6 +6,7 @@
6
6
  * [Client](client.md)
7
7
  * [Response](response.md)
8
8
  * [Quick Start](quick-start.md)
9
+ * [Error Handling](error-handling.md)
9
10
  * [Resources](resources/README.md)
10
11
  * [Account](resources/account/README.md)
11
12
  * [#accounts](resources/account/accounts.md)
@@ -26,3 +26,15 @@ require "monday_ruby"
26
26
  client = Monday::Client.new(token: <AUTH_TOKEN>)
27
27
  ```
28
28
 
29
+ You can optionally pass in the version of the API you want to use using the `version` configuration field.
30
+
31
+ By default, the latest stable version is used. Read more about the version on monday.com's [official documentation](https://developer.monday.com/api-reference/docs/api-versioning).
32
+
33
+ ```ruby
34
+ require "monday_ruby"
35
+
36
+ Monday.configure do |config|
37
+ config.token = <AUTH_TOKEN>
38
+ config.version = "2023-07"
39
+ end
40
+ ```
@@ -0,0 +1,71 @@
1
+ # Error Handling
2
+
3
+ Monday.com has a set of predefined errors and exceptions that are sent back from their GraphQL API. Refer to their [official documentation](https://developer.monday.com/api-reference/docs/errors) to know more about the error codes.
4
+
5
+ ### Catching exceptions
6
+
7
+ If there is an error from the API, the library raises an exception. It's a best practice to catch and handle exceptions.
8
+
9
+ To catch an exception, use the `rescue` keyword. You can catch all the exceptions from the API using the `Monday::Error` class. However, it is recommended to catch specific exceptions using its subclasses and have a fallback rescue using `Monday::Error`.
10
+
11
+ ```ruby
12
+ require "monday_ruby"
13
+
14
+ client = Monday::Client.new(token: <AUTH_TOKEN>)
15
+
16
+ def example
17
+ res = client.boards
18
+ puts res.body
19
+ rescue Monday::AuthorizationError => error
20
+ puts "Authorization error: #{error.message}"
21
+ puts "Error code: #{error.code}"
22
+ rescue Monday::Error => error
23
+ puts "Other error: #{error.message}"
24
+ end
25
+ ```
26
+
27
+ Along with the default status code exceptions, monday.com returns some other exceptions with `200` status code. This library handles those errors and raises exceptions accordingly.
28
+
29
+ #### `Monday::InternalServer Error`
30
+
31
+ This exception is raised when the server returns a `500` status code. Read more about what can cause this error on Monday.com's [official documentation](https://developer.monday.com/api-reference/docs/errors#internal-server-error).
32
+
33
+ #### `Monday::AuthorizationError`
34
+
35
+ This exception is raised when the server returns a `401` or a `403` status code. This can happen when the client is not authenticated, i.e., not configured with the token, or the token is incorrect.
36
+
37
+ This exception is also raised when the server returns a `200` status code but the body returns `UserUnauthorizedException` error code.
38
+
39
+ #### `Monday::RateLimitError`
40
+
41
+ This exception is raised when the server returns a `429` status code. This can happen when you exceed the rate limit, i.e., 5,000 requests per minute. Read more about their rate limit on their [official documentation](https://developer.monday.com/api-reference/docs/rate-limits).
42
+
43
+ #### `Monday::ResourceNotFoundError`
44
+
45
+ This exception is raised when the server returns a `404` status code. This can happen when you pass an invalid ID in the query.
46
+
47
+ This exception is also raised when the server returns a `200` status code but the body returns `ResourceNotFoundException` error code.
48
+
49
+ #### `Monday::ComplexityError`
50
+
51
+ This exception is raised when the server returns a `200` status code but the body returns `ComplexityException` error code.
52
+
53
+ #### `Monday::InvalidRequestError`
54
+
55
+ This exception is raised when the server returns a `400` status code. This can happen when the query you pass is invalid.
56
+
57
+ This exception is also raised when the server returns a `200` status code but the body returns the following error codes:
58
+
59
+ 1. `InvalidUserIdException`
60
+ 2. `InvalidVersionException`
61
+ 3. `InvalidColumnIdException`
62
+ 4. `InvalidItemIdException`
63
+ 5. `InvalidBoardIdException`
64
+ 6. `InvalidArgumentException`
65
+ 7. `CreateBoardException`
66
+ 8. `ItemsLimitationException`
67
+ 9. `ItemNameTooLongException`
68
+ 10. `ColumnValueException`
69
+ 11. `CorrectedValueException`
70
+
71
+ Read more about these specific exceptions on their [official API documentation](https://developer.monday.com/api-reference/docs/errors).
data/lib/monday/client.rb CHANGED
@@ -9,6 +9,7 @@ require_relative "request"
9
9
  require_relative "response"
10
10
  require_relative "resources"
11
11
  require_relative "util"
12
+ require_relative "error"
12
13
 
13
14
  module Monday
14
15
  # Client executes requests against the monday.com's API and
@@ -30,7 +31,7 @@ module Monday
30
31
  def config_options(config_args)
31
32
  return Monday.config if config_args.empty?
32
33
 
33
- Monday::Configuration.new(**config_args)
34
+ Configuration.new(**config_args)
34
35
  end
35
36
 
36
37
  def uri
@@ -45,8 +46,34 @@ module Monday
45
46
  end
46
47
 
47
48
  def make_request(body)
48
- response = Monday::Request.post(uri, body, request_headers)
49
- Monday::Response.new(response)
49
+ response = Request.post(uri, body, request_headers)
50
+
51
+ handle_response(Response.new(response))
52
+ end
53
+
54
+ def handle_response(response)
55
+ return response if response.success?
56
+
57
+ raise_errors(response)
58
+ end
59
+
60
+ def raise_errors(response)
61
+ raise default_exception(response) unless (200..299).cover?(response.status)
62
+
63
+ raise response_exception(response)
64
+ end
65
+
66
+ def response_exception(response)
67
+ error_code = response.body["error_code"]
68
+
69
+ return Error.new(response: response) if error_code.nil?
70
+
71
+ exception_klass, code = Util.response_error_exceptions_mapping(error_code)
72
+ exception_klass.new(message: error_code, response: response, code: code)
73
+ end
74
+
75
+ def default_exception(response)
76
+ Util.status_code_exceptions_mapping(response.status).new(response: response)
50
77
  end
51
78
  end
52
79
  end
@@ -10,10 +10,12 @@ module Monday
10
10
  class Configuration
11
11
  DEFAULT_HOST = "https://api.monday.com/v2"
12
12
  DEFAULT_TOKEN = nil
13
+ DEFAULT_VERSION = "2023-07"
13
14
 
14
15
  CONFIGURATION_FIELDS = %i[
15
16
  token
16
17
  host
18
+ version
17
19
  ].freeze
18
20
 
19
21
  attr_accessor(*CONFIGURATION_FIELDS)
@@ -24,6 +26,7 @@ module Monday
24
26
 
25
27
  @host = DEFAULT_HOST
26
28
  @token = DEFAULT_TOKEN
29
+ @version = DEFAULT_VERSION
27
30
 
28
31
  config_args.each do |key, value|
29
32
  public_send("#{key}=", value)
@@ -33,6 +36,7 @@ module Monday
33
36
  def reset
34
37
  @token = DEFAULT_TOKEN
35
38
  @host = DEFAULT_HOST
39
+ @version = DEFAULT_VERSION
36
40
  end
37
41
  end
38
42
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Monday
4
+ # Monday::Error is the base error class from which other
5
+ # specific error classes are derived.
6
+ class Error < StandardError
7
+ attr_reader :response, :message, :code
8
+
9
+ def initialize(message: nil, response: nil, code: nil)
10
+ @response = response
11
+ @message = error_message(message)
12
+ @code = error_code(code)
13
+
14
+ super(@message)
15
+ end
16
+
17
+ def error_data
18
+ return {} if response&.body&.dig("error_data").nil?
19
+
20
+ response.body["error_data"]
21
+ end
22
+
23
+ private
24
+
25
+ def error_code(code)
26
+ return code unless code.nil?
27
+
28
+ response_error_code.nil? ? response&.status : response_error_code
29
+ end
30
+
31
+ def error_message(message)
32
+ return response_error_message if message.nil?
33
+ return message if response_error_message.nil?
34
+
35
+ "#{message}: #{response_error_message}"
36
+ end
37
+
38
+ def response_error_code
39
+ return if response.nil?
40
+
41
+ response.body["status_code"]
42
+ end
43
+
44
+ def response_error_message
45
+ return if response.nil?
46
+
47
+ response.body["error_message"].nil? ? response.body["errors"].to_s : response.body["error_message"].to_s
48
+ end
49
+ end
50
+
51
+ # InternalServerError is raised when the request returns
52
+ # a 500 status code.
53
+ class InternalServerError < Error
54
+ end
55
+
56
+ # AuthorizationError is raised when the request returns
57
+ # a 401 or 403 status code.
58
+ #
59
+ # It is also raised when the body returns the following error_code:
60
+ # UserUnauthorizedException
61
+ class AuthorizationError < Error
62
+ end
63
+
64
+ # RateLimitError is raised when the request returns
65
+ # a 429 status code.
66
+ class RateLimitError < Error
67
+ end
68
+
69
+ # ResourceNotFoundError is raised when the request returns
70
+ # a 404 status code.
71
+ #
72
+ # It is also raised when the body returns the following error_code:
73
+ # ResourceNotFoundException
74
+ class ResourceNotFoundError < Error
75
+ end
76
+
77
+ # ResourceNotFoundError is raised when the request returns
78
+ # a 400 status code.
79
+ #
80
+ # It is also raised when the body returns the following error_codes:
81
+ # InvalidUserIdException, InvalidVersionException, InvalidColumnIdException
82
+ # InvalidItemIdException, InvalidBoardIdException, InvalidArgumentException
83
+ # CreateBoardException, ItemsLimitationException, ItemNameTooLongException
84
+ # ColumnValueException, CorrectedValueException
85
+ class InvalidRequestError < Error
86
+ end
87
+
88
+ # ComplexityError is raised when the body returns the following error_code:
89
+ # ComplexityException
90
+ class ComplexityError < Error
91
+ end
92
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Monday
4
+ module Resources
5
+ # Represents Monday.com's workspace resource.
6
+ module Workspace
7
+ DEFAULT_SELECT = %w[id name description].freeze
8
+
9
+ # Retrieves all the workspaces.
10
+ #
11
+ # Allows filtering workspaces using the args option.
12
+ # Allows customizing the values to retrieve using the select option.
13
+ # By default, ID, name and description fields are retrieved.
14
+ def workspaces(args: {}, select: DEFAULT_SELECT)
15
+ query = "query { workspaces(#{Util.format_args(args)}) {#{Util.format_select(select)}}}"
16
+
17
+ make_request(query)
18
+ end
19
+
20
+ # Creates a new workspaces.
21
+ #
22
+ # Allows customizing creating a workspace using the args option.
23
+ # Allows customizing the values to retrieve using the select option.
24
+ # By default, ID, name and description fields are retrieved.
25
+ def create_workspace(args: {}, select: DEFAULT_SELECT)
26
+ query = "mutation { create_workspace(#{Util.format_args(args)}) {#{Util.format_select(select)}}}"
27
+
28
+ make_request(query)
29
+ end
30
+
31
+ # Deletes a workspace.
32
+ #
33
+ # Requires workspace_id to delete the workspace.
34
+ # Allows customizing the values to retrieve using the select option.
35
+ # By default, returns the ID of the workspace deleted.
36
+ def delete_workspace(workspace_id, select: ["id"])
37
+ query = "mutation { delete_workspace(workspace_id: #{workspace_id}) {#{Util.format_select(select)}}}"
38
+
39
+ make_request(query)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -6,6 +6,7 @@ require_relative "resources/board"
6
6
  require_relative "resources/board_view"
7
7
  require_relative "resources/column"
8
8
  require_relative "resources/item"
9
+ require_relative "resources/workspace"
9
10
 
10
11
  module Monday
11
12
  module Resources
@@ -15,5 +16,6 @@ module Monday
15
16
  include BoardView
16
17
  include Column
17
18
  include Item
19
+ include Workspace
18
20
  end
19
21
  end
@@ -6,6 +6,9 @@ module Monday
6
6
  #
7
7
  # Returns status code, parsed body and headers.
8
8
  class Response
9
+ ERROR_OBJECT_KEYS = %w[errors error_code error_message].freeze
10
+ private_constant :ERROR_OBJECT_KEYS
11
+
9
12
  attr_reader :status, :body, :headers
10
13
 
11
14
  def initialize(response)
@@ -26,7 +29,7 @@ module Monday
26
29
  attr_reader :response
27
30
 
28
31
  def errors?
29
- parse_body.key?("errors") || parse_body.key?("error_message")
32
+ (parse_body.keys & ERROR_OBJECT_KEYS).any?
30
33
  end
31
34
 
32
35
  def parse_body
data/lib/monday/util.rb CHANGED
@@ -25,6 +25,37 @@ module Monday
25
25
  values
26
26
  end
27
27
 
28
+ def status_code_exceptions_mapping(status_code)
29
+ {
30
+ "500" => InternalServerError,
31
+ "429" => RateLimitError,
32
+ "404" => ResourceNotFoundError,
33
+ "403" => AuthorizationError,
34
+ "401" => AuthorizationError,
35
+ "400" => InvalidRequestError
36
+ }[status_code.to_s] || Error
37
+ end
38
+
39
+ def response_error_exceptions_mapping(error_code)
40
+ {
41
+ "ComplexityException" => [ComplexityError, 429],
42
+ "UserUnauthorizedException" => [AuthorizationError, 403],
43
+ "ResourceNotFoundException" => [ResourceNotFoundError, 404],
44
+ "InvalidUserIdException" => [InvalidRequestError, 400],
45
+ "InvalidVersionException" => [InvalidRequestError, 400],
46
+ "InvalidColumnIdException" => [InvalidRequestError, 400],
47
+ "InvalidItemIdException" => [InvalidRequestError, 400],
48
+ "InvalidBoardIdException" => [InvalidRequestError, 400],
49
+ "InvalidArgumentException" => [InvalidRequestError, 400],
50
+ "CreateBoardException" => [InvalidRequestError, 400],
51
+ "ItemsLimitationException" => [InvalidRequestError, 400],
52
+ "ItemNameTooLongException" => [InvalidRequestError, 400],
53
+ "ColumnValueException" => [InvalidRequestError, 400],
54
+ "CorrectedValueException" => [InvalidRequestError, 400],
55
+ "InvalidWorkspaceIdException" => [InvalidRequestError, 400]
56
+ }[error_code] || [Error, 400]
57
+ end
58
+
28
59
  private
29
60
 
30
61
  def format_array(array)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Monday
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/monday_ruby.gemspec CHANGED
@@ -8,8 +8,8 @@ repository = "https://github.com/sanifhimani/monday_ruby"
8
8
  Gem::Specification.new do |spec|
9
9
  spec.name = "monday_ruby"
10
10
  spec.version = version
11
- spec.authors = ["Sanif Himani"]
12
- spec.email = ["sanifhimani92@gmail.com"]
11
+ spec.authors = ["Sanif Himani", "Wes Hays"]
12
+ spec.email = ["sanifhimani92@gmail.com", "weshays@gmail.com"]
13
13
 
14
14
  spec.summary = "Ruby bindings to use the monday.com API"
15
15
  spec.description = "A Gem to easily interact with monday.com API using native Ruby"
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monday_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sanif Himani
8
+ - Wes Hays
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2023-07-04 00:00:00.000000000 Z
12
+ date: 2023-09-18 00:00:00.000000000 Z
12
13
  dependencies: []
13
14
  description: A Gem to easily interact with monday.com API using native Ruby
14
15
  email:
15
16
  - sanifhimani92@gmail.com
17
+ - weshays@gmail.com
16
18
  executables: []
17
19
  extensions: []
18
20
  extra_rdoc_files: []
@@ -23,6 +25,7 @@ files:
23
25
  - ".vscode/settings.json"
24
26
  - CHANGELOG.md
25
27
  - CODE_OF_CONDUCT.md
28
+ - CONTRIBUTING.md
26
29
  - LICENSE
27
30
  - README.md
28
31
  - Rakefile
@@ -30,6 +33,7 @@ files:
30
33
  - docs/SUMMARY.md
31
34
  - docs/client.md
32
35
  - docs/configuration.md
36
+ - docs/error-handling.md
33
37
  - docs/getting-started.md
34
38
  - docs/quick-start.md
35
39
  - docs/resources/README.md
@@ -66,6 +70,7 @@ files:
66
70
  - docs/response.md
67
71
  - lib/monday/client.rb
68
72
  - lib/monday/configuration.rb
73
+ - lib/monday/error.rb
69
74
  - lib/monday/request.rb
70
75
  - lib/monday/resources.rb
71
76
  - lib/monday/resources/account.rb
@@ -74,6 +79,7 @@ files:
74
79
  - lib/monday/resources/board_view.rb
75
80
  - lib/monday/resources/column.rb
76
81
  - lib/monday/resources/item.rb
82
+ - lib/monday/resources/workspace.rb
77
83
  - lib/monday/response.rb
78
84
  - lib/monday/util.rb
79
85
  - lib/monday/version.rb
@@ -85,7 +91,7 @@ licenses:
85
91
  metadata:
86
92
  homepage_uri: https://github.com/sanifhimani/monday_ruby
87
93
  documentation_uri: https://monday-ruby.gitbook.io/docs/
88
- changelog_uri: https://github.com/sanifhimani/monday_ruby/blob/v0.2.0/CHANGELOG.md
94
+ changelog_uri: https://github.com/sanifhimani/monday_ruby/blob/v0.4.0/CHANGELOG.md
89
95
  rubygems_mfa_required: 'true'
90
96
  post_install_message:
91
97
  rdoc_options: []
@@ -102,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
108
  - !ruby/object:Gem::Version
103
109
  version: '0'
104
110
  requirements: []
105
- rubygems_version: 3.4.14
111
+ rubygems_version: 3.4.19
106
112
  signing_key:
107
113
  specification_version: 4
108
114
  summary: Ruby bindings to use the monday.com API