my_api_client 0.14.0.pre → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
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?