my_api_client 0.14.0.pre → 0.17.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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +179 -38
  3. data/.dependabot/config.yml +19 -1
  4. data/.envrc.skeleton +1 -0
  5. data/.rubocop.yml +9 -1
  6. data/.rubocop_challenge.yml +5 -0
  7. data/.rubocop_todo.yml +29 -1
  8. data/CHANGELOG.md +177 -1
  9. data/Gemfile.lock +47 -45
  10. data/README.jp.md +156 -21
  11. data/bin/console +4 -0
  12. data/example/api_clients/application_api_client.rb +13 -0
  13. data/example/api_clients/my_error_api_client.rb +34 -0
  14. data/example/api_clients/my_errors.rb +27 -0
  15. data/example/api_clients/my_pagination_api_client.rb +18 -0
  16. data/example/api_clients/my_rest_api_client.rb +48 -0
  17. data/example/api_clients/my_status_api_client.rb +22 -0
  18. data/lib/generators/rails/templates/application_api_client.rb.erb +0 -11
  19. data/lib/generators/rspec/templates/api_client_spec.rb.erb +22 -15
  20. data/lib/my_api_client.rb +7 -0
  21. data/lib/my_api_client/base.rb +4 -2
  22. data/lib/my_api_client/default_error_handlers.rb +64 -0
  23. data/lib/my_api_client/error_handling.rb +6 -6
  24. data/lib/my_api_client/error_handling/generator.rb +23 -7
  25. data/lib/my_api_client/errors.rb +1 -53
  26. data/lib/my_api_client/errors/api_limit_error.rb +6 -0
  27. data/lib/my_api_client/errors/client_error.rb +93 -0
  28. data/lib/my_api_client/errors/network_error.rb +43 -0
  29. data/lib/my_api_client/errors/server_error.rb +42 -0
  30. data/lib/my_api_client/request.rb +29 -34
  31. data/lib/my_api_client/request/basic.rb +32 -0
  32. data/lib/my_api_client/request/executor.rb +1 -1
  33. data/lib/my_api_client/request/pagination.rb +39 -0
  34. data/lib/my_api_client/rspec/matchers/request_to.rb +3 -4
  35. data/lib/my_api_client/version.rb +1 -1
  36. data/my_api/.envrc.skeleton +3 -0
  37. data/my_api/.gitignore +14 -0
  38. data/my_api/.jetskeep +1 -0
  39. data/my_api/.rspec +3 -0
  40. data/my_api/.ruby-version +1 -0
  41. data/my_api/Gemfile +23 -0
  42. data/my_api/Gemfile.lock +243 -0
  43. data/my_api/Procfile +7 -0
  44. data/my_api/README.md +54 -0
  45. data/my_api/Rakefile +4 -0
  46. data/my_api/app/controllers/application_controller.rb +5 -0
  47. data/my_api/app/controllers/error_controller.rb +21 -0
  48. data/my_api/app/controllers/pagination_controller.rb +58 -0
  49. data/my_api/app/controllers/rest_controller.rb +60 -0
  50. data/my_api/app/controllers/status_controller.rb +11 -0
  51. data/my_api/app/helpers/application_helper.rb +5 -0
  52. data/my_api/app/jobs/application_job.rb +7 -0
  53. data/my_api/app/models/application_item.rb +5 -0
  54. data/my_api/config.ru +7 -0
  55. data/my_api/config/application.rb +73 -0
  56. data/my_api/config/dynamodb.yml +22 -0
  57. data/my_api/config/environments/development.rb +9 -0
  58. data/my_api/config/environments/production.rb +11 -0
  59. data/my_api/config/environments/test.rb +9 -0
  60. data/my_api/config/routes.rb +17 -0
  61. data/my_api/db/.gitkeep +0 -0
  62. data/my_api/public/404.html +67 -0
  63. data/my_api/public/422.html +67 -0
  64. data/my_api/public/500.html +66 -0
  65. data/my_api/public/favicon.ico +0 -0
  66. data/my_api/public/index.html +91 -0
  67. data/my_api/spec/controllers/error_controller_spec.rb +43 -0
  68. data/my_api/spec/controllers/pagination_controller_spec.rb +73 -0
  69. data/my_api/spec/controllers/rest_controller_spec.rb +99 -0
  70. data/my_api/spec/controllers/status_controller_spec.rb +47 -0
  71. data/my_api/spec/fixtures/payloads/posts-index.json +51 -0
  72. data/my_api/spec/fixtures/payloads/posts-show.json +53 -0
  73. data/my_api/spec/spec_helper.rb +31 -0
  74. data/rails_app/rails_5.2/.rspec +3 -0
  75. data/rails_app/rails_5.2/Gemfile +18 -0
  76. data/rails_app/rails_5.2/Gemfile.lock +171 -0
  77. data/rails_app/rails_5.2/README.md +24 -0
  78. data/rails_app/rails_5.2/Rakefile +8 -0
  79. data/rails_app/rails_5.2/app/controllers/application_controller.rb +4 -0
  80. data/rails_app/rails_5.2/app/jobs/application_job.rb +4 -0
  81. data/rails_app/rails_5.2/bin/bundle +5 -0
  82. data/rails_app/rails_5.2/bin/rails +6 -0
  83. data/rails_app/rails_5.2/bin/rake +6 -0
  84. data/rails_app/rails_5.2/bin/setup +27 -0
  85. data/rails_app/rails_5.2/bin/update +27 -0
  86. data/rails_app/rails_5.2/config.ru +7 -0
  87. data/rails_app/rails_5.2/config/application.rb +37 -0
  88. data/rails_app/rails_5.2/config/boot.rb +6 -0
  89. data/rails_app/rails_5.2/config/credentials.yml.enc +1 -0
  90. data/rails_app/rails_5.2/config/environment.rb +7 -0
  91. data/rails_app/rails_5.2/config/environments/development.rb +41 -0
  92. data/rails_app/rails_5.2/config/environments/production.rb +70 -0
  93. data/rails_app/rails_5.2/config/environments/test.rb +38 -0
  94. data/rails_app/rails_5.2/config/initializers/application_controller_renderer.rb +9 -0
  95. data/rails_app/rails_5.2/config/initializers/backtrace_silencers.rb +8 -0
  96. data/rails_app/rails_5.2/config/initializers/cors.rb +17 -0
  97. data/rails_app/rails_5.2/config/initializers/filter_parameter_logging.rb +6 -0
  98. data/rails_app/rails_5.2/config/initializers/inflections.rb +17 -0
  99. data/rails_app/rails_5.2/config/initializers/mime_types.rb +5 -0
  100. data/rails_app/rails_5.2/config/initializers/wrap_parameters.rb +11 -0
  101. data/rails_app/rails_5.2/config/locales/en.yml +33 -0
  102. data/rails_app/rails_5.2/config/routes.rb +5 -0
  103. data/rails_app/rails_5.2/config/spring.rb +8 -0
  104. data/rails_app/rails_5.2/public/robots.txt +1 -0
  105. data/rails_app/rails_5.2/spec/rails_helper.rb +14 -0
  106. data/rails_app/rails_5.2/spec/spec_helper.rb +13 -0
  107. data/rails_app/rails_6.0/.rspec +3 -0
  108. data/rails_app/rails_6.0/Gemfile +17 -0
  109. data/rails_app/rails_6.0/Gemfile.lock +186 -0
  110. data/rails_app/rails_6.0/README.md +24 -0
  111. data/rails_app/rails_6.0/Rakefile +8 -0
  112. data/rails_app/rails_6.0/app/controllers/application_controller.rb +4 -0
  113. data/rails_app/rails_6.0/app/jobs/application_job.rb +9 -0
  114. data/rails_app/rails_6.0/bin/rails +6 -0
  115. data/rails_app/rails_6.0/bin/rake +6 -0
  116. data/rails_app/rails_6.0/bin/setup +27 -0
  117. data/rails_app/rails_6.0/config.ru +7 -0
  118. data/rails_app/rails_6.0/config/application.rb +39 -0
  119. data/rails_app/rails_6.0/config/boot.rb +6 -0
  120. data/rails_app/rails_6.0/config/credentials.yml.enc +1 -0
  121. data/rails_app/rails_6.0/config/environment.rb +7 -0
  122. data/rails_app/rails_6.0/config/environments/development.rb +39 -0
  123. data/rails_app/rails_6.0/config/environments/production.rb +90 -0
  124. data/rails_app/rails_6.0/config/environments/test.rb +41 -0
  125. data/rails_app/rails_6.0/config/initializers/application_controller_renderer.rb +9 -0
  126. data/rails_app/rails_6.0/config/initializers/backtrace_silencers.rb +8 -0
  127. data/rails_app/rails_6.0/config/initializers/cors.rb +17 -0
  128. data/rails_app/rails_6.0/config/initializers/filter_parameter_logging.rb +6 -0
  129. data/rails_app/rails_6.0/config/initializers/inflections.rb +17 -0
  130. data/rails_app/rails_6.0/config/initializers/mime_types.rb +5 -0
  131. data/rails_app/rails_6.0/config/initializers/wrap_parameters.rb +11 -0
  132. data/rails_app/rails_6.0/config/locales/en.yml +33 -0
  133. data/rails_app/rails_6.0/config/routes.rb +5 -0
  134. data/rails_app/rails_6.0/config/spring.rb +8 -0
  135. data/rails_app/rails_6.0/public/robots.txt +1 -0
  136. data/rails_app/rails_6.0/spec/rails_helper.rb +14 -0
  137. data/rails_app/rails_6.0/spec/spec_helper.rb +13 -0
  138. metadata +120 -5
  139. data/renovate.json +0 -21
@@ -3,6 +3,10 @@
3
3
 
4
4
  require 'bundler/setup'
5
5
  require 'my_api_client'
6
+ require './example/api_clients/my_error_api_client'
7
+ require './example/api_clients/my_rest_api_client'
8
+ require './example/api_clients/my_pagination_api_client'
9
+ require './example/api_clients/my_status_api_client'
6
10
 
7
11
  # You can add fixtures and/or initialization code here to make experimenting
8
12
  # with your gem easier. You can also use a different console, if you like.
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'my_errors'
4
+
5
+ # An usage example of the `my_api_client`.
6
+ class ApplicationApiClient < MyApiClient::Base
7
+ endpoint ENV['MY_API_ENDPOINT']
8
+
9
+ self.logger = ::Logger.new(nil)
10
+
11
+ http_open_timeout 5.seconds
12
+ http_read_timeout 5.seconds
13
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_api_client'
4
+
5
+ # An usage example of the `my_api_client`.
6
+ # See also: my_api/app/controllers/status_controller.rb
7
+ class MyErrorApiClient < ApplicationApiClient
8
+ error_handling json: { '$.error.message': /You requested error code/ },
9
+ raise: MyErrors::ErrorCodeOther
10
+
11
+ error_handling json: { '$.error.code': :zero? },
12
+ raise: MyErrors::ErrorCode00
13
+
14
+ error_handling json: { '$.error.code': 10 },
15
+ raise: MyErrors::ErrorCode10
16
+
17
+ error_handling json: { '$.error.code': 20..29 },
18
+ raise: MyErrors::ErrorCode2x
19
+
20
+ error_handling json: { '$.error.code': 30 },
21
+ status_code: 400,
22
+ raise: MyErrors::ErrorCode30
23
+
24
+ # GET error/:code
25
+ def get_error(code:)
26
+ get "error/#{code}", headers: headers
27
+ end
28
+
29
+ private
30
+
31
+ def headers
32
+ { 'Content-Type': 'application/json;charset=UTF-8' }
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyErrors
4
+ # 400 Bad Request
5
+ class BadRequest < MyApiClient::ClientError; end
6
+
7
+ # 401 Unauthorized
8
+ class Unauthorized < MyApiClient::ClientError; end
9
+
10
+ # 403 Forbidden
11
+ class Forbidden < MyApiClient::ClientError; end
12
+
13
+ # Error code: 0
14
+ class ErrorCode00 < MyApiClient::ClientError; end
15
+
16
+ # Error code: 10
17
+ class ErrorCode10 < MyApiClient::ClientError; end
18
+
19
+ # Error code: 20 to 29
20
+ class ErrorCode2x < MyApiClient::ClientError; end
21
+
22
+ # Error code: 30
23
+ class ErrorCode30 < MyApiClient::ClientError; end
24
+
25
+ # Error code: other
26
+ class ErrorCodeOther < MyApiClient::ClientError; end
27
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_api_client'
4
+
5
+ # An usage example of the `my_api_client`.
6
+ # See also: my_api/app/controllers/pagination_controller.rb
7
+ class MyPaginationApiClient < ApplicationApiClient
8
+ # GET pagination?page=1
9
+ def pagination
10
+ pget 'pagination', paging: '$.links.next', headers: headers, query: { page: 1 }
11
+ end
12
+
13
+ private
14
+
15
+ def headers
16
+ { 'Content-Type': 'application/json;charset=UTF-8' }
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_api_client'
4
+
5
+ # An usage example of the `my_api_client`.
6
+ # See also: my_api/app/controllers/rest_controller.rb
7
+ class MyRestApiClient < ApplicationApiClient
8
+ # GET rest
9
+ def get_posts(order: :asc)
10
+ order = :desc unless order == :asc
11
+ query = { order: order }
12
+ get 'rest', query: query, headers: headers
13
+ end
14
+
15
+ # GET rest/:id
16
+ def get_post(id:)
17
+ get "rest/#{id}", headers: headers
18
+ end
19
+
20
+ # POST rest
21
+ def post_post(title:)
22
+ body = { title: title }
23
+ post 'rest', body: body, headers: headers
24
+ end
25
+
26
+ # PUT rest/:id
27
+ def put_post(id:, title:)
28
+ body = { title: title }
29
+ put "rest/#{id}", body: body, headers: headers
30
+ end
31
+
32
+ # PATCH rest/:id
33
+ def patch_post(id:, title:)
34
+ body = { title: title }
35
+ patch "rest/#{id}", body: body, headers: headers
36
+ end
37
+
38
+ # DELETE rest/:id
39
+ def delete_post(id:)
40
+ delete "rest/#{id}", headers: headers
41
+ end
42
+
43
+ private
44
+
45
+ def headers
46
+ { 'Content-Type': 'application/json;charset=UTF-8' }
47
+ end
48
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_api_client'
4
+
5
+ # An usage example of the `my_api_client`.
6
+ # See also: my_api/app/controllers/status_controller.rb
7
+ class MyStatusApiClient < ApplicationApiClient
8
+ error_handling status_code: 400, raise: MyErrors::BadRequest
9
+ error_handling status_code: 401, raise: MyErrors::Unauthorized
10
+ error_handling status_code: 403, raise: MyErrors::Forbidden
11
+
12
+ # GET status/:status
13
+ def get_status(status:)
14
+ get "status/#{status}", headers: headers
15
+ end
16
+
17
+ private
18
+
19
+ def headers
20
+ { 'Content-Type': 'application/json;charset=UTF-8' }
21
+ end
22
+ end
@@ -20,15 +20,4 @@ class ApplicationApiClient < MyApiClient::Base
20
20
  # seconds.
21
21
  #
22
22
  # http_read_timeout 3.seconds
23
-
24
- # Catch the exception and re-execution after any seconds, like as ActiveJob.
25
- # Please note that it is executed as a synchronous process unlike ActiveJob.
26
- #
27
- # retry_on MyApiClient::NetworkError, wait: 5.seconds, attempts: 3
28
-
29
- # Set a HTTP response verifyment and behavior. If conflicting conditions are
30
- # set, the processing defined later takes precedence
31
- #
32
- # error_handling status_code: 400..499, raise: MyApiClient::ClientError
33
- # error_handling status_code: 500..599, raise: MyApiClient::ServerError
34
23
  end
@@ -11,16 +11,28 @@ RSpec.describe <%= "#{class_name}ApiClient" %>, <%= type_metatag(:api_client) %>
11
11
  end
12
12
 
13
13
  shared_examples 'to handle errors' do
14
- it do
15
- expect { api_request }
16
- .to be_handled_as_an_error(MyApiClient::ClientError)
17
- .when_receive(status_code: 400)
14
+ context 'when the API returns 200 OK' do
15
+ it do
16
+ expect { api_request }
17
+ .not_to be_handled_as_an_error
18
+ .when_receive(status_code: 200)
19
+ end
18
20
  end
19
21
 
20
- it do
21
- expect { api_request }
22
- .to be_handled_as_an_error(MyApiClient::ServerError)
23
- .when_receive(status_code: 500)
22
+ context 'when the API returns 400 Bad Request' do
23
+ it do
24
+ expect { api_request }
25
+ .to be_handled_as_an_error(MyApiClient::ClientError::BadRequest)
26
+ .when_receive(status_code: 400)
27
+ end
28
+ end
29
+
30
+ context 'when the API returns 500 Internal Server Error' do
31
+ it do
32
+ expect { api_request }
33
+ .to be_handled_as_an_error(MyApiClient::ServerError::InternalServerError)
34
+ .when_receive(status_code: 500)
35
+ end
24
36
  end
25
37
  end
26
38
  <% yeild_request_arguments do |action, http_method, pathname| -%>
@@ -28,6 +40,8 @@ RSpec.describe <%= "#{class_name}ApiClient" %>, <%= type_metatag(:api_client) %>
28
40
  describe '#<%= action %>' do
29
41
  subject(:api_request) { api_client.<%= action %> }
30
42
 
43
+ it_behaves_like 'to handle errors'
44
+
31
45
  it do
32
46
  expect { api_request }
33
47
  .to request_to(:<%= http_method %>, 'https://example.com/<%= pathname %>')
@@ -37,13 +51,6 @@ RSpec.describe <%= "#{class_name}ApiClient" %>, <%= type_metatag(:api_client) %>
37
51
  .with(headers: headers, body: {})
38
52
  <% end -%>
39
53
  end
40
-
41
- it_behaves_like 'to handle errors' do
42
- it do
43
- expect { api_request }.not_to be_handled_as_an_error
44
- .when_receive(status_code: 200, body: nil, headers: nil)
45
- end
46
- end
47
54
  end
48
55
  <% end -%>
49
56
  end
@@ -16,7 +16,14 @@ require 'my_api_client/error_handling'
16
16
  require 'my_api_client/exceptions'
17
17
  require 'my_api_client/request/logger'
18
18
  require 'my_api_client/request/executor'
19
+ require 'my_api_client/request/basic'
20
+ require 'my_api_client/request/pagination'
19
21
  require 'my_api_client/errors'
22
+ require 'my_api_client/errors/api_limit_error'
23
+ require 'my_api_client/errors/client_error'
24
+ require 'my_api_client/errors/network_error'
25
+ require 'my_api_client/errors/server_error'
26
+ require 'my_api_client/default_error_handlers'
20
27
  require 'my_api_client/params/params'
21
28
  require 'my_api_client/params/request'
22
29
  require 'my_api_client/request'
@@ -9,15 +9,17 @@ module MyApiClient
9
9
  include MyApiClient::Request
10
10
 
11
11
  if ActiveSupport::VERSION::STRING >= '5.2.0'
12
- class_attribute :logger, instance_writer: false, default: ::Logger.new(STDOUT)
12
+ class_attribute :logger, instance_writer: false, default: ::Logger.new($stdout)
13
13
  class_attribute :error_handlers, instance_writer: false, default: []
14
14
  else
15
15
  class_attribute :logger
16
16
  class_attribute :error_handlers
17
- self.logger = ::Logger.new(STDOUT)
17
+ self.logger = ::Logger.new($stdout)
18
18
  self.error_handlers = []
19
19
  end
20
20
 
21
+ include MyApiClient::DefaultErrorHandlers
22
+
21
23
  # NOTE: This class **MUST NOT** implement #initialize method. Because it
22
24
  # will become constraint that need call #super in the #initialize at
23
25
  # definition of the child classes.
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ # Provides default error handlers.
5
+ module DefaultErrorHandlers
6
+ extend ActiveSupport::Concern
7
+
8
+ # rubocop:disable Metrics/BlockLength
9
+ included do
10
+ # NOTE: The built-in error handlers are following. Although they are prepared
11
+ # to save the trouble of defining, but you can override any error handlers
12
+ # in your API client class.
13
+ error_handling status_code: 400..499, raise: ClientError
14
+ error_handling status_code: 400, raise: ClientError::BadRequest
15
+ error_handling status_code: 401, raise: ClientError::Unauthorized
16
+ error_handling status_code: 402, raise: ClientError::PaymentRequired
17
+ error_handling status_code: 403, raise: ClientError::Forbidden
18
+ error_handling status_code: 404, raise: ClientError::NotFound
19
+ error_handling status_code: 405, raise: ClientError::MethodNotAllowed
20
+ error_handling status_code: 406, raise: ClientError::NotAcceptable
21
+ error_handling status_code: 407, raise: ClientError::ProxyAuthenticationRequired
22
+ error_handling status_code: 408, raise: ClientError::RequestTimeout
23
+ error_handling status_code: 409, raise: ClientError::Conflict
24
+ error_handling status_code: 410, raise: ClientError::Gone
25
+ error_handling status_code: 411, raise: ClientError::LengthRequired
26
+ error_handling status_code: 412, raise: ClientError::PreconditionFailed
27
+ error_handling status_code: 413, raise: ClientError::RequestEntityTooLarge
28
+ error_handling status_code: 414, raise: ClientError::RequestUriTooLong
29
+ error_handling status_code: 415, raise: ClientError::UnsupportedMediaType
30
+ error_handling status_code: 416, raise: ClientError::RequestedRangeNotSatisfiable
31
+ error_handling status_code: 417, raise: ClientError::ExpectationFailed
32
+ error_handling status_code: 418, raise: ClientError::IamTeapot
33
+ error_handling status_code: 421, raise: ClientError::MisdirectedRequest
34
+ error_handling status_code: 422, raise: ClientError::UnprocessableEntity
35
+ error_handling status_code: 423, raise: ClientError::Locked
36
+ error_handling status_code: 424, raise: ClientError::FailedDependency
37
+ error_handling status_code: 425, raise: ClientError::TooEarly
38
+ error_handling status_code: 426, raise: ClientError::UpgradeRequired
39
+ error_handling status_code: 428, raise: ClientError::PreconditionRequired
40
+ error_handling status_code: 429, raise: ClientError::TooManyRequests
41
+ error_handling status_code: 431, raise: ClientError::RequestHeaderFieldsTooLarge
42
+ error_handling status_code: 451, raise: ClientError::UnavailableForLegalReasons
43
+
44
+ error_handling status_code: 500..599, raise: ServerError
45
+ error_handling status_code: 500, raise: ServerError::InternalServerError
46
+ error_handling status_code: 501, raise: ServerError::NotImplemented
47
+ error_handling status_code: 502, raise: ServerError::BadGateway
48
+ error_handling status_code: 503, raise: ServerError::ServiceUnavailable
49
+ error_handling status_code: 504, raise: ServerError::GatewayTimeout
50
+ error_handling status_code: 505, raise: ServerError::HttpVersionNotSupported
51
+ error_handling status_code: 506, raise: ServerError::VariantAlsoNegotiates
52
+ error_handling status_code: 507, raise: ServerError::InsufficientStorage
53
+ error_handling status_code: 508, raise: ServerError::LoopDetected
54
+ error_handling status_code: 509, raise: ServerError::BandwidthLimitExceeded
55
+ error_handling status_code: 510, raise: ServerError::NotExtended
56
+ error_handling status_code: 511, raise: ServerError::NetworkAuthenticationRequired
57
+
58
+ # Catch the exception and re-execution after any seconds, like as ActiveJob.
59
+ # Please note that it is executed as a synchronous process unlike ActiveJob.
60
+ retry_on NetworkError, wait: 0.3.seconds, attempts: 3
61
+ end
62
+ # rubocop:enable Metrics/BlockLength
63
+ end
64
+ end
@@ -9,9 +9,8 @@ module MyApiClient
9
9
  # @example
10
10
  # error_handling status_code: 200, json: :forbid_nil
11
11
  # error_handling status_code: 400..499, raise: MyApiClient::ClientError
12
- # error_handling status_code: 500..599 do |params, logger|
12
+ # error_handling status_code: 500..599, raise: MyApiClient::ServerError do |params, logger|
13
13
  # logger.warn 'Server error occurred.'
14
- # raise MyApiClient::ServerError, params
15
14
  # end
16
15
  #
17
16
  # error_handling json: { '$.errors.code': 10..19 }, with: :my_error_handling
@@ -29,10 +28,11 @@ module MyApiClient
29
28
  # @option status_code [String, Range, Integer, Regexp]
30
29
  # Verifies response HTTP status code and raises error if matched
31
30
  # @option json [Hash, Symbol]
32
- # Verifies response body as JSON and raises error if matched.
33
- # If specified `:forbid_nil`, it forbid `nil` on response_body.
31
+ # Specify the validation target value path included in the response body
32
+ # as JsonPath expression.
33
+ # If specified `:forbid_nil`, it forbid `nil` at the response body.
34
34
  # @option with [Symbol]
35
- # Calls specified method when error detected
35
+ # Calls specified method before raising exception when error detected.
36
36
  # @option raise [MyApiClient::Error]
37
37
  # Raises specified error when an invalid response detected.
38
38
  # Should be inherited `MyApiClient::Error` class.
@@ -41,7 +41,7 @@ module MyApiClient
41
41
  # If the error detected, retries the API request. Requires `raise` option.
42
42
  # You can set `true` or `retry_on` options (`wait` and `attempts`).
43
43
  # @yield [MyApiClient::Params::Params, MyApiClient::Request::Logger]
44
- # Executes the block when error detected.
44
+ # Executes the block before raising exception when error detected.
45
45
  # Forbid to be used with the` retry` option.
46
46
  def error_handling(**options, &block)
47
47
  options[:block] = block
@@ -23,8 +23,8 @@ module MyApiClient
23
23
  # Raises specified error when error detected. default: MyApiClient::Error
24
24
  # @option block [Proc]
25
25
  # Executes the block when error detected
26
- # @return [Proc]
27
- # Returns value as `Proc`.
26
+ # @return [Proc, nil]
27
+ # Returns the error handler as "Proc". If no error occurs, return `nil`.
28
28
  def initialize(**options)
29
29
  options[:raise] ||= MyApiClient::Error
30
30
  verify_and_set_arguments(**options)
@@ -43,14 +43,32 @@ module MyApiClient
43
43
 
44
44
  def generate_error_handler
45
45
  if _block
46
- ->(params, logger) { _block.call(params, logger) }
46
+ block_caller
47
47
  elsif _with
48
- ->(params, logger) { _instance.send(_with, params, logger) }
48
+ method_caller
49
49
  else
50
- ->(params, _) { raise _raise, params }
50
+ error_raiser
51
51
  end
52
52
  end
53
53
 
54
+ def block_caller
55
+ lambda { |params, logger|
56
+ _block.call(params, logger)
57
+ error_raiser.call(params, logger)
58
+ }
59
+ end
60
+
61
+ def method_caller
62
+ lambda { |params, logger|
63
+ _instance.send(_with, params, logger)
64
+ error_raiser.call(params, logger)
65
+ }
66
+ end
67
+
68
+ def error_raiser
69
+ ->(params, _) { raise _raise, params }
70
+ end
71
+
54
72
  # Verify given options and raise error if they are incorrect.
55
73
  # If not, set them to instance variables.
56
74
  #
@@ -67,7 +85,6 @@ module MyApiClient
67
85
  end
68
86
  end
69
87
 
70
- # rubocop:disable Metrics/CyclomaticComplexity
71
88
  def match?(operator, target)
72
89
  case operator
73
90
  when nil
@@ -84,7 +101,6 @@ module MyApiClient
84
101
  raise "Unexpected operator type was given: #{operator.inspect}"
85
102
  end
86
103
  end
87
- # rubocop:enable Metrics/CyclomaticComplexity
88
104
 
89
105
  def match_all?(json, response_body)
90
106
  return true if json.nil?