monday_ruby 0.2.0 → 0.3.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: b952365eaf332b933932dea993d33470bc585c9eadcf0dc7525e4550794313d2
4
+ data.tar.gz: 665a9d53d8a06972f88022040a28bf8003fa13247aa0bdac60e21f7ca8be9da5
5
5
  SHA512:
6
- metadata.gz: d594d0addabe0adbb550ecf474e12c4d7645e10bdf37a9fe10c7b930ab63d954204c1658f30dd6258303c2b7c1e8fb6ace0476beb23fbf91fc864f9dfb4f6fe4
7
- data.tar.gz: e42cdc2c6bcf6de3d5652e5bfa9c3d86f377155f0c2e06e76c2857b691341eca3e115e6abc8811fa02976afcda4997f8f3feffbc3f16b058bf4f3b9849c69835
6
+ metadata.gz: 2af82867a8586bb1bdd6f665f6e584b9e41ea76d0a74fab00f56d408d4357fee4986fde25df96403f0ba8284a4ecc99c61e97e1a4e9668e6024ca7e94574a22e
7
+ data.tar.gz: 7b66ffafb1c9bfd6bb5c24de9c19438acf89ba59a0a07204ca76a38e18bd043e183077ccda3042453560f71f18c307c73bf8b6f1d161e75a42a39bcadb468229
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,11 @@
1
+ ## v0.3.0 (July 10, 2023)
2
+
3
+ ### Added
4
+
5
+ - Improved error handling
6
+ - Support to configure the API version
7
+ - Coverage report
8
+
1
9
  ## v0.2.0 (July 04, 2023)
2
10
 
3
11
  ### Added
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-10"
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
@@ -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,36 @@ 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
+ }[error_code] || [Error, 400]
56
+ end
57
+
28
58
  private
29
59
 
30
60
  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.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
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.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sanif Himani
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-04 00:00:00.000000000 Z
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A Gem to easily interact with monday.com API using native Ruby
14
14
  email:
@@ -30,6 +30,7 @@ files:
30
30
  - docs/SUMMARY.md
31
31
  - docs/client.md
32
32
  - docs/configuration.md
33
+ - docs/error-handling.md
33
34
  - docs/getting-started.md
34
35
  - docs/quick-start.md
35
36
  - docs/resources/README.md
@@ -66,6 +67,7 @@ files:
66
67
  - docs/response.md
67
68
  - lib/monday/client.rb
68
69
  - lib/monday/configuration.rb
70
+ - lib/monday/error.rb
69
71
  - lib/monday/request.rb
70
72
  - lib/monday/resources.rb
71
73
  - lib/monday/resources/account.rb
@@ -85,7 +87,7 @@ licenses:
85
87
  metadata:
86
88
  homepage_uri: https://github.com/sanifhimani/monday_ruby
87
89
  documentation_uri: https://monday-ruby.gitbook.io/docs/
88
- changelog_uri: https://github.com/sanifhimani/monday_ruby/blob/v0.2.0/CHANGELOG.md
90
+ changelog_uri: https://github.com/sanifhimani/monday_ruby/blob/v0.3.0/CHANGELOG.md
89
91
  rubygems_mfa_required: 'true'
90
92
  post_install_message:
91
93
  rdoc_options: []