api_client_builder 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rubocop.yml +34 -0
  4. data/.travis.yml +14 -12
  5. data/LICENSE.txt +1 -1
  6. data/README.md +47 -50
  7. data/api_client_builder.gemspec +13 -12
  8. data/build.sh +16 -3
  9. data/lib/api_client_builder.rb +13 -9
  10. data/lib/api_client_builder/api_client.rb +1 -7
  11. data/lib/api_client_builder/get_collection_request.rb +2 -2
  12. data/lib/api_client_builder/get_item_request.rb +0 -2
  13. data/lib/api_client_builder/post_request.rb +0 -2
  14. data/lib/api_client_builder/put_request.rb +0 -2
  15. data/lib/api_client_builder/request.rb +6 -6
  16. data/lib/api_client_builder/url_generator.rb +3 -5
  17. data/lib/api_client_builder/version.rb +1 -1
  18. data/spec/lib/api_client_builder/api_client_spec.rb +3 -4
  19. data/spec/lib/api_client_builder/get_collection_request_spec.rb +7 -10
  20. data/spec/lib/api_client_builder/get_item_request_spec.rb +4 -6
  21. data/spec/lib/api_client_builder/post_request_spec.rb +3 -5
  22. data/spec/lib/api_client_builder/put_request_spec.rb +3 -5
  23. data/spec/lib/api_client_builder/request_spec.rb +7 -9
  24. data/spec/lib/api_client_builder/response_spec.rb +1 -2
  25. data/spec/lib/api_client_builder/test_client/client.rb +2 -3
  26. data/spec/lib/api_client_builder/test_client/http_client_handler.rb +1 -2
  27. data/spec/lib/api_client_builder/test_client/response_handler.rb +9 -14
  28. data/spec/lib/api_client_builder/url_generator_spec.rb +8 -7
  29. data/spec/spec_helper.rb +8 -2
  30. metadata +35 -22
  31. data/.dockerignore +0 -1
  32. data/Dockerfile +0 -16
  33. data/api_client_builder-1.0.0.gem +0 -0
  34. data/docker-compose.yml +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 325e44729f05185e293461182fd2f405824ef233
4
- data.tar.gz: 44970894a7563a62609223a3efd9b7d38a0ce557
3
+ metadata.gz: 8fd053293f5d2e0c724f2c149c68a814099179e9
4
+ data.tar.gz: 28db90774bea6b541e632e74e578b933d3a92e54
5
5
  SHA512:
6
- metadata.gz: edcc960fa01482a12446b8be86a847df5d93a500559901758c410e5cf44d6773e251306b4783821b6b9e9741e10429333a9daaae49da285f937a759b9237e18e
7
- data.tar.gz: a9e4eec3e7d812ca887b39324c9fd4ee0d21737d31d8c177df431c40393aea6861aea2936b27a3d0e90a89c0f08849f7e2045b9be56beb1b6a52703294fb310c
6
+ metadata.gz: e693b8c048a88dcd3e68332817afff076a684329b699588bac2706a450510a4c4ad7d32669c344f9fb59b0784562f4612efa84c6befa062416417eb9629b13b8
7
+ data.tar.gz: c813e8124cdaaa0869ae53ee613aa97df839740b883a1a86d0076f8bd2e60cde29c0a5dbf812a12bce8d57982c10cc6dfb4b7af28e9104e76ad3a21190e1d277
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
- Gemfile.lock
1
+ /coverage
2
+ /Gemfile.lock
3
+ /*.gem
@@ -0,0 +1,34 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - spec/**/*.rb
7
+
8
+ Metrics/LineLength:
9
+ Max: 120 # Default: 80
10
+
11
+ Metrics/MethodLength:
12
+ Max: 20 # Default: 10
13
+
14
+ Naming/AccessorMethodName: # TODO: Enable and fix API at some point.
15
+ Enabled: false
16
+
17
+ Style/Documentation:
18
+ # This cop checks for missing top-level documentation of classes and modules.
19
+ # Classes with no body and namespace modules are exempt from the check.
20
+ # Namespace modules are modules that have nothing in their bodies except
21
+ # classes or other modules.
22
+ Enabled: false
23
+
24
+ Style/FrozenStringLiteralComment:
25
+ # `when_needed` will add the frozen string literal comment to files
26
+ # only when the `TargetRubyVersion` is set to 2.3+.
27
+ # `always` will always add the frozen string literal comment to a file
28
+ # regardless of the Ruby version or if `freeze` or `<<` are called on a
29
+ # string literal. If you run code against multiple versions of Ruby, it is
30
+ # possible that this will create errors in Ruby 2.3.0+.
31
+ #
32
+ # See: https://wyeworks.com/blog/2015/12/1/immutable-strings-in-ruby-2-dot-3
33
+ EnforcedStyle: when_needed
34
+ Enabled: false
@@ -1,18 +1,20 @@
1
- language: ruby
1
+ dist: trusty
2
2
  sudo: false
3
+ language: ruby
3
4
  cache: bundler
5
+
4
6
  rvm:
5
- # - ruby-head
6
- - 2.1
7
- - 2.2
8
7
  - 2.3
8
+ - 2.4
9
+ - 2.5
10
+
9
11
  matrix:
10
12
  fast_finish: true
11
- # WWTD doesn't support allow_failures... yet
12
- # allow_failures:
13
- # - rvm: ruby-head
14
- script: bundle exec rspec
15
- notifications:
16
- email:
17
- on_success: never
18
- on_failure: never
13
+
14
+ before_install: gem update bundler
15
+ bundler_args: --jobs 3
16
+ install: bundle install --jobs 3
17
+
18
+ script:
19
+ - bundle exec rubocop --fail-level autocorrect
20
+ - bundle exec rspec
@@ -1,4 +1,4 @@
1
- Copyright (c) 2016 Instructure Inc.
1
+ Copyright (c) 2016-2018 Instructure Inc.
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -3,7 +3,9 @@
3
3
  API Client Builder was created to reduce the overhead of creating API clients.
4
4
 
5
5
  It provides a DSL for defining endpoints and only requires you to define handlers
6
- for http requests and responses.
6
+ for HTTP requests and responses.
7
+
8
+ [![Build Status](https://travis-ci.org/instructure/api-client-builder.svg?branch=master)](https://travis-ci.org/instructure/api-client-builder)
7
9
 
8
10
  ---
9
11
 
@@ -28,10 +30,6 @@ Or install it yourself as:
28
30
  The basic client structure looks like this.
29
31
 
30
32
  ```ruby
31
- require 'api_client_builder/api_client'
32
- require 'path/to/your/http_client_handler'
33
- require 'path/to/your/response_handler'
34
-
35
33
  class Client < APIClientBulder::APIClient
36
34
  def initialize(**opts)
37
35
  super(domain: opts[:domain],
@@ -55,8 +53,8 @@ def response_handler_build(http_client, start_url, type)
55
53
  end
56
54
  ```
57
55
 
58
-
59
56
  ### Defining routes on the client
57
+
60
58
  To define routes on the api client, use the DSL provided by the
61
59
  builder's APIClient class. Four parts have been defined to help:
62
60
 
@@ -81,7 +79,6 @@ builder's APIClient class. Four parts have been defined to help:
81
79
  - Note that any symbols in the route will be interpolated as required
82
80
  params when calling the method on the client.
83
81
 
84
-
85
82
  ---
86
83
 
87
84
  ## Route Examples
@@ -91,7 +88,7 @@ builder's APIClient class. Four parts have been defined to help:
91
88
  Define the route on the client
92
89
 
93
90
  ```ruby
94
- get :some_object, :singular, 'some_objects/:id'
91
+ get :some_object, :singular, 'some_objects/:id'
95
92
  ```
96
93
 
97
94
  Use the defined route
@@ -107,7 +104,7 @@ response_body = single_request.response
107
104
  Define the route on the client
108
105
 
109
106
  ```ruby
110
- get :some_objects, :collection, 'some_objects'
107
+ get :some_objects, :collection, 'some_objects'
111
108
  ```
112
109
 
113
110
  Use the defined route
@@ -116,7 +113,7 @@ Use the defined route
116
113
  collection_request = client.get_some_objects
117
114
 
118
115
  collection_request.each do |item|
119
- #Item will be a Hash if you use the default response in the response handler
116
+ # Item will be a Hash if you use the default response in the response handler
120
117
  end
121
118
  ```
122
119
 
@@ -166,16 +163,16 @@ get :some_objects_for_course, :collection, 'course/:course_id/some_objects'
166
163
 
167
164
  ## Defining an HTTP Client Handler
168
165
 
169
- The HTTP Client Handler is designed to manage the http requests themselves. Since
166
+ The HTTP Client Handler is designed to manage the HTTP requests themselves. Since
170
167
  actually making an HTTP request typically requires some amount of authentication,
171
168
  it is suggested that authentication and headers are managed here as well.
172
169
 
173
- The http client handler requires '#get', '#post', and '#put' to be defined here
170
+ The HTTP client handler requires '#get', '#post', and '#put' to be defined here
174
171
  with the shown method signature.
175
172
 
176
173
  ```ruby
177
174
  class HTTPClientHandler
178
- #Do initialization here, generally authentication creds and a domain is sent in
175
+ # Do initialization here, generally authentication creds and a domain is sent in
179
176
 
180
177
  def get(route, params = nil, headers = {})
181
178
  client.get(route, params, headers)
@@ -189,9 +186,9 @@ class HTTPClientHandler
189
186
  client.post(route, params, headers)
190
187
  end
191
188
 
192
- #Define a client to use here. The HTTPClient gem is a good option
189
+ # Define a client to use here. The HTTPClient gem is a good option
193
190
 
194
- #Build up headers and authentication handling here as well
191
+ # Build up headers and authentication handling here as well
195
192
  end
196
193
  ```
197
194
 
@@ -219,11 +216,11 @@ these actions simpler.
219
216
 
220
217
  ```ruby
221
218
  class ResponseHandler
222
- def initialize(http_client_handler, start_url, type)
223
- @http_client = http_client_handler
224
- @start_url = start_url
225
- @type = type
226
- end
219
+ def initialize(http_client_handler, start_url, type)
220
+ @http_client = http_client_handler
221
+ @start_url = start_url
222
+ @type = type
223
+ end
227
224
  end
228
225
  ```
229
226
 
@@ -239,13 +236,13 @@ of pages and also start the page counter.
239
236
 
240
237
  ```ruby
241
238
  def get_first_page
242
- #Build the URL -- this could be to add pagination params to the route, or add
243
- # whatever else is necessary to the route
239
+ # Build the URL -- this could be to add pagination params to the route, or
240
+ # add whatever else is necessary to the route.
244
241
  http_response = @http_client.get("a URL")
245
242
 
246
- #Generally the first page will contain information about how many pages a paginated
247
- # response will have. Set that here. `@max_pages`
248
- #Be sure to set the current page count as well -- @current_page
243
+ # Generally the first page will contain information about how many pages a
244
+ # paginated response will have. Set that here: `@max_pages`
245
+ # Be sure to set the current page count as well: `@current_page`
249
246
  build_response(http_response)
250
247
  end
251
248
  ```
@@ -258,17 +255,16 @@ return a boolean denoting the presence of more pages.
258
255
 
259
256
  ```ruby
260
257
  def get_next_page
261
- #Build the URL -- this could be to add pagination params to the route, or add
262
- # whatever else is necessary to the route
258
+ # Build the URL -- this could be to add pagination params to the route, or
259
+ # add whatever else is necessary to the route:
263
260
  http_response = @http_client.get("a URL")
264
261
 
265
- #If the http_response is valid then increment the page counter here
262
+ # If the http_response is valid then increment the page counter here.
266
263
  build_response(http_response)
267
264
  end
268
265
 
269
266
  def more_pages?
270
- return false if @current_page > @max_pages
271
- return true
267
+ @current_page < @max_pages
272
268
  end
273
269
  ```
274
270
 
@@ -278,9 +274,9 @@ The builder will call `#put_request` when handling put routes.
278
274
 
279
275
  ```ruby
280
276
  def put_request
281
- #Build the URL -- this could be to add pagination params to the route, or add
282
- # whatever else is necessary to the route
283
- #Also send the body if thats how the client handler is configured
277
+ # Build the URL -- this could be to add pagination params to the route, or
278
+ # add whatever else is necessary to the route.
279
+ # Also send the body if thats how the client handler is configured.
284
280
  http_response = @http_client.put("a URL", {})
285
281
  build_response(http_response)
286
282
  end
@@ -292,9 +288,9 @@ The builder will call `#post_request` when handling post routes.
292
288
 
293
289
  ```ruby
294
290
  def post_request
295
- #Build the URL -- this could be to add pagination params to the route, or add
296
- # whatever else is necessary to the route
297
- #Also send the body if thats how the client handler is configured
291
+ # Build the URL -- this could be to add pagination params to the route, or
292
+ # add whatever else is necessary to the route.
293
+ # Also send the body if that's how the client handler is configured.
298
294
  http_response = @http_client.post("a URL", {})
299
295
  build_response(http_response)
300
296
  end
@@ -308,34 +304,35 @@ the following methods.
308
304
  ```ruby
309
305
  def retryable?(status_code)
310
306
  if @opts[:exponential_backoff]
311
- #Define the conditions of whether or not the provided status code is retry-able
307
+ # Define the conditions of whether or not the provided status code is retry-able
308
+ true
312
309
  else
313
- return false
310
+ false
314
311
  end
315
312
  end
316
313
 
317
314
  def reset_retries
318
- #Track the number of retries so the request is not retried indefinitely.
319
- # The builder will reset them when it no longer is retrying by calling this
320
- # method
315
+ # Track the number of retries so the request is not retried indefinitely.
316
+ # The builder will reset them when it no longer is retrying by calling this
317
+ # method.
321
318
  @retries = 0
322
319
  end
323
320
 
324
321
  def retry_request
325
- #Increment the retries here so the request is not retried indefinitely.
322
+ # Increment the retries here so the request is not retried indefinitely.
326
323
  @retries += 1
327
324
 
328
- #Build the URL -- this could be to add pagination params to the route, or add
329
- # whatever else is necessary to the route
325
+ # Build the URL -- this could be to add pagination params to the route, or
326
+ # add whatever else is necessary to the route.
330
327
  response = @http_client.the_action_to_retry("a URL")
331
328
  build_response(response)
332
329
  end
333
330
  ```
334
331
 
335
- #### Managing the http response
332
+ #### Managing the HTTP response
336
333
 
337
334
  The builder defines a default `Response` object that will provide the minimally
338
- required interface for managing an http response.
335
+ required interface for managing an HTTP response.
339
336
 
340
337
  ```ruby
341
338
  def build_response(http_response)
@@ -373,10 +370,10 @@ is not a "success."
373
370
  single_request = client.get_some_object(id: 123)
374
371
 
375
372
  single_request.on_error do |page, handler|
376
- #The page will have all of the status information
377
- #The handler is the defined response_handler
378
- #Use either to glean more information about why the request was an error and
379
- # handle the error here
373
+ # The page will have all of the status information.
374
+ # The handler is the defined response_handler.
375
+ # Use either to glean more information about why the request was an error and
376
+ # handle the error here.
380
377
  end
381
378
 
382
379
  response_body = single_request.response
@@ -1,24 +1,25 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/api_client_builder/version', __FILE__)
1
+ require File.expand_path('lib/api_client_builder/version', __dir__)
3
2
 
4
3
  Gem::Specification.new do |gem|
5
- gem.name = "api_client_builder"
6
- gem.summary = "API Client Builder provides an easy to use interface for creating HTTP api clients"
7
- gem.description = "API Client Builder provides an easy to use interface for creating HTTP api clients"
8
- gem.authors = ['Jayce Higgins']
9
- gem.email = ['jhiggins@instructure.com', 'eng@instructure.com']
4
+ gem.name = 'api_client_builder'
5
+ gem.summary = 'API Client Builder provides an easy to use interface for creating HTTP api clients'
6
+ gem.description = 'API Client Builder provides an easy to use interface for creating HTTP api clients'
7
+ gem.authors = ['Jayce Higgins', 'Bryan Petty']
8
+ gem.email = ['jhiggins@instructure.com', 'bpetty@instructure.com', 'eng@instructure.com']
9
+ gem.homepage = 'https://github.com/instructure/api-client-builder'
10
10
 
11
11
  gem.version = APIClientBuilder::VERSION
12
- gem.required_ruby_version = '>= 2.0'
12
+ gem.required_ruby_version = '>= 2.3'
13
13
 
14
- gem.license = 'MIT'
14
+ gem.license = 'MIT'
15
15
 
16
16
  gem.add_development_dependency 'pry'
17
- gem.add_development_dependency 'rspec'
18
- gem.add_development_dependency 'wwtd'
17
+ gem.add_development_dependency 'rspec', '~> 3.7'
18
+ gem.add_development_dependency 'rubocop', '~> 0.57.2'
19
+ gem.add_development_dependency 'simplecov', '~> 0'
19
20
 
20
21
  gem.files = `git ls-files`.split("\n")
21
22
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
23
  gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
23
- gem.require_paths = ["lib"]
24
+ gem.require_paths = ['lib']
24
25
  end
data/build.sh CHANGED
@@ -1,4 +1,17 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
 
3
- docker-compose build --pull
4
- docker-compose run test
3
+ set -e
4
+
5
+ docker pull ruby:2.3
6
+ docker pull ruby:2.4
7
+ docker pull ruby:2.5
8
+
9
+ docker run --rm -v "`pwd`:/app" -w /app --user `id -u`:`id -g` -e HOME="/tmp" "ruby:2.3" \
10
+ /bin/sh -c "echo \"gem: --no-document\" >> ~/.gemrc && bundle install --jobs 5 --quiet && bundle exec rubocop --cache false --fail-level autocorrect"
11
+
12
+ for version in '2.3' '2.4' '2.5'; do
13
+ echo "Testing Ruby $version..."
14
+ docker run --rm -v "`pwd`:/app" -w /app --user `id -u`:`id -g` \
15
+ -e HOME="/tmp" "ruby:$version" /bin/sh -c \
16
+ "echo \"gem: --no-document\" >> ~/.gemrc && bundle install --jobs 5 --quiet && bundle exec rspec"
17
+ done
@@ -1,9 +1,13 @@
1
- require 'api_client_builder/version'
2
- require 'api_client_builder/api_client'
3
- require 'api_client_builder/get_collection_request'
4
- require 'api_client_builder/get_item_request'
5
- require 'api_client_builder/post_request'
6
- require 'api_client_builder/put_request'
7
- require 'api_client_builder/request'
8
- require 'api_client_builder/response'
9
- require 'api_client_builder/url_generator'
1
+ require 'uri'
2
+
3
+ require_relative 'api_client_builder/version'
4
+ require_relative 'api_client_builder/request'
5
+ require_relative 'api_client_builder/response'
6
+
7
+ require_relative 'api_client_builder/get_collection_request'
8
+ require_relative 'api_client_builder/get_item_request'
9
+ require_relative 'api_client_builder/post_request'
10
+ require_relative 'api_client_builder/put_request'
11
+ require_relative 'api_client_builder/url_generator'
12
+
13
+ require_relative 'api_client_builder/api_client'
@@ -1,9 +1,3 @@
1
- require 'api_client_builder/get_collection_request'
2
- require 'api_client_builder/get_item_request'
3
- require 'api_client_builder/post_request'
4
- require 'api_client_builder/put_request'
5
- require 'api_client_builder/url_generator'
6
-
7
1
  module APIClientBuilder
8
2
  # The base APIClient that defines the interface for defining an API Client.
9
3
  # Should be sub-classed and then provided an HTTPClient handler and a
@@ -28,7 +22,7 @@ module APIClientBuilder
28
22
  # @param route [String] defines the routes endpoint
29
23
  #
30
24
  # @return [Request] either a GetCollection or GetItem request
31
- def self.get(type, plurality, route, **opts)
25
+ def self.get(type, plurality, route, **_opts)
32
26
  if plurality == :collection
33
27
  define_method("get_#{type}") do |**params|
34
28
  GetCollectionRequest.new(
@@ -1,5 +1,3 @@
1
- require 'api_client_builder/request'
2
-
3
1
  module APIClientBuilder
4
2
  # The multi item response object to be used as the container for
5
3
  # collection responses from the defined API
@@ -11,6 +9,7 @@ module APIClientBuilder
11
9
  # strategy is defined concretely on the response handler.
12
10
  #
13
11
  # @return [JSON] the http response body
12
+ # rubocop:disable Metrics/AbcSize
14
13
  def each
15
14
  if block_given?
16
15
  each_page do |page|
@@ -32,6 +31,7 @@ module APIClientBuilder
32
31
  Enumerator.new(self, :each)
33
32
  end
34
33
  end
34
+ # rubocop:enable Metrics/AbcSize
35
35
 
36
36
  private
37
37
 
@@ -1,5 +1,3 @@
1
- require 'api_client_builder/request'
2
-
3
1
  module APIClientBuilder
4
2
  # The single item response object to be used as the container for
5
3
  # singular responses from the defined API
@@ -1,5 +1,3 @@
1
- require 'api_client_builder/request'
2
-
3
1
  module APIClientBuilder
4
2
  class PostRequest < Request
5
3
  # Yields the response body if the response was successful. Will call
@@ -1,5 +1,3 @@
1
- require 'api_client_builder/request'
2
-
3
1
  module APIClientBuilder
4
2
  class PutRequest < Request
5
3
  # Yields the response body if the response was successful. Will call
@@ -1,5 +1,5 @@
1
1
  module APIClientBuilder
2
- class DefaultPageError < StandardError;end
2
+ class DefaultPageError < StandardError; end
3
3
 
4
4
  class Request
5
5
  attr_reader :type, :response_handler, :body, :error_handlers_collection
@@ -23,11 +23,11 @@ module APIClientBuilder
23
23
  # @return [Array<Block>] the error handlers collection
24
24
  def error_handlers
25
25
  if error_handlers_collection.empty?
26
- self.on_error do |page, handler|
27
- raise DefaultPageError,
28
- "Default error for bad response. If you want to handle this" \
29
- " error use #on_error on the response" \
30
- " in your api consumer. Error Code: #{page.status_code}"
26
+ on_error do |page, _handler|
27
+ raise DefaultPageError, <<~MESSAGE
28
+ Default error for bad response. If you want to handle this error use #on_error
29
+ on the response in your api consumer. Error Code: #{page.status_code}.
30
+ MESSAGE
31
31
  end
32
32
  end
33
33
  error_handlers_collection
@@ -1,7 +1,5 @@
1
- require 'uri'
2
-
3
1
  module APIClientBuilder
4
- class NoURLError < StandardError;end
2
+ class NoURLError < StandardError; end
5
3
  class URLGenerator
6
4
  # Receives a domain and parses it into a URI
7
5
  #
@@ -23,8 +21,8 @@ module APIClientBuilder
23
21
  #
24
22
  # @return [URI] the fully built route
25
23
  def build_route(route, **params)
26
- string_params = route.split('/').select{|param| param.start_with?(':')}
27
- symboled_params = string_params.map{|param| param.tr(':', '').to_sym}
24
+ string_params = route.split('/').select { |param| param.start_with?(':') }
25
+ symboled_params = string_params.map { |param| param.tr(':', '').to_sym }
28
26
 
29
27
  new_route = route.clone
30
28
  symboled_params.each do |param|
@@ -1,3 +1,3 @@
1
1
  module APIClientBuilder
2
- VERSION = '1.0.1' unless defined?(APIClientBuilder::VERSION)
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -1,11 +1,10 @@
1
1
  require 'spec_helper'
2
- require 'lib/api_client_builder/test_client/client'
3
- require 'api_client_builder/api_client'
2
+ require_relative 'test_client/client'
4
3
 
5
4
  module APIClientBuilder
6
5
  describe APIClient do
7
- let(:domain) {'https://www.domain.com/api/endpoints/'}
8
- let(:client) {TestClient::Client.new(domain: domain)}
6
+ let(:domain) { 'https://www.domain.com/api/endpoints/' }
7
+ let(:client) { TestClient::Client.new(domain: domain) }
9
8
 
10
9
  describe '.get' do
11
10
  context 'plurality is :collection' do
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'api_client_builder/get_collection_request'
3
- require 'lib/api_client_builder/test_client/client'
2
+ require_relative 'test_client/client'
4
3
 
5
4
  module APIClientBuilder
6
5
  describe GetCollectionRequest do
@@ -21,9 +20,8 @@ module APIClientBuilder
21
20
  bad_response = APIClientBuilder::Response.new('bad request', 500, [200])
22
21
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:get_first_page).and_return(bad_response)
23
22
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(bad_response)
24
- expect{ client.get_some_objects.each{} }.to raise_error(
25
- APIClientBuilder::DefaultPageError,
26
- "Default error for bad response. If you want to handle this error use #on_error on the response in your api consumer. Error Code: 500"
23
+ expect { client.get_some_objects.each {} }.to raise_error(
24
+ APIClientBuilder::DefaultPageError, /Error Code: 500/
27
25
  )
28
26
  end
29
27
 
@@ -32,7 +30,7 @@ module APIClientBuilder
32
30
  client = TestClient::Client.new(domain: 'https://www.domain.com/api/endpoints/')
33
31
 
34
32
  bad_response = APIClientBuilder::Response.new('bad request', 500, [200])
35
- good_response = APIClientBuilder::Response.new([1,2,3], 200, [200])
33
+ good_response = APIClientBuilder::Response.new([1, 2, 3], 200, [200])
36
34
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:get_first_page).and_return(bad_response)
37
35
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:more_pages?).and_return(false)
38
36
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(good_response)
@@ -47,13 +45,12 @@ module APIClientBuilder
47
45
  client = TestClient::Client.new(domain: 'https://www.domain.com/api/endpoints/')
48
46
 
49
47
  bad_response = APIClientBuilder::Response.new('bad request', 400, [200])
50
- good_response = APIClientBuilder::Response.new([1,2,3], 200, [200])
48
+ good_response = APIClientBuilder::Response.new([1, 2, 3], 200, [200])
51
49
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:get_first_page).and_return(bad_response)
52
50
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:more_pages?).and_return(false)
53
51
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(good_response)
54
- expect{ client.get_some_objects.each{} }.to raise_error(
55
- APIClientBuilder::DefaultPageError,
56
- "Default error for bad response. If you want to handle this error use #on_error on the response in your api consumer. Error Code: 400"
52
+ expect { client.get_some_objects.each {} }.to raise_error(
53
+ APIClientBuilder::DefaultPageError, /Error Code: 400/
57
54
  )
58
55
  end
59
56
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'api_client_builder/get_item_request'
3
- require 'lib/api_client_builder/test_client/client'
2
+ require_relative 'test_client/client'
4
3
 
5
4
  module APIClientBuilder
6
5
  describe GetItemRequest do
@@ -21,9 +20,8 @@ module APIClientBuilder
21
20
  bad_response = APIClientBuilder::Response.new('bad request', 500, [200])
22
21
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:get_first_page).and_return(bad_response)
23
22
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(bad_response)
24
- expect{ client.get_some_object(some_id: '123').response }.to raise_error(
25
- APIClientBuilder::DefaultPageError,
26
- "Default error for bad response. If you want to handle this error use #on_error on the response in your api consumer. Error Code: 500"
23
+ expect { client.get_some_object(some_id: '123').response }.to raise_error(
24
+ APIClientBuilder::DefaultPageError, /Error Code: 500/
27
25
  )
28
26
  end
29
27
 
@@ -32,7 +30,7 @@ module APIClientBuilder
32
30
  client = TestClient::Client.new(domain: 'https://www.domain.com/api/endpoints/')
33
31
 
34
32
  bad_response = APIClientBuilder::Response.new('bad request', 500, [200])
35
- good_response = APIClientBuilder::Response.new([1,2,3], 200, [200])
33
+ good_response = APIClientBuilder::Response.new([1, 2, 3], 200, [200])
36
34
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:get_first_page).and_return(bad_response)
37
35
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:more_pages?).and_return(false)
38
36
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(good_response)
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'api_client_builder/post_request'
3
- require 'lib/api_client_builder/test_client/client'
2
+ require_relative 'test_client/client'
4
3
 
5
4
  module APIClientBuilder
6
5
  describe PostRequest do
@@ -20,9 +19,8 @@ module APIClientBuilder
20
19
 
21
20
  bad_response = APIClientBuilder::Response.new('bad request', 400, [200])
22
21
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:post_request).and_return(bad_response)
23
- expect{ client.post_some_object({}).response }.to raise_error(
24
- APIClientBuilder::DefaultPageError,
25
- "Default error for bad response. If you want to handle this error use #on_error on the response in your api consumer. Error Code: 400"
22
+ expect { client.post_some_object({}).response }.to raise_error(
23
+ APIClientBuilder::DefaultPageError, /Error Code: 400/
26
24
  )
27
25
  end
28
26
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'api_client_builder/put_request'
3
- require 'lib/api_client_builder/test_client/client'
2
+ require_relative 'test_client/client'
4
3
 
5
4
  module APIClientBuilder
6
5
  describe PutRequest do
@@ -20,9 +19,8 @@ module APIClientBuilder
20
19
 
21
20
  bad_response = APIClientBuilder::Response.new('bad request', 400, [200])
22
21
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:put_request).and_return(bad_response)
23
- expect{ client.put_some_object({}).response }.to raise_error(
24
- APIClientBuilder::DefaultPageError,
25
- "Default error for bad response. If you want to handle this error use #on_error on the response in your api consumer. Error Code: 400"
22
+ expect { client.put_some_object({}).response }.to raise_error(
23
+ APIClientBuilder::DefaultPageError, /Error Code: 400/
26
24
  )
27
25
  end
28
26
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'lib/api_client_builder/test_client/client'
3
- require 'api_client_builder/request'
2
+ require_relative 'test_client/client'
4
3
 
5
4
  module APIClientBuilder
6
5
  describe Request do
@@ -12,9 +11,8 @@ module APIClientBuilder
12
11
  bad_response = APIClientBuilder::Response.new('bad request', 400, [200])
13
12
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:get_first_page).and_return(bad_response)
14
13
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(bad_response)
15
- expect{ client.get_some_object(some_id: '123').response }.to raise_error(
16
- APIClientBuilder::DefaultPageError,
17
- "Default error for bad response. If you want to handle this error use #on_error on the response in your api consumer. Error Code: 400"
14
+ expect { client.get_some_object(some_id: '123').response }.to raise_error(
15
+ APIClientBuilder::DefaultPageError, /Error Code: 400/
18
16
  )
19
17
  end
20
18
  end
@@ -28,13 +26,13 @@ module APIClientBuilder
28
26
  allow_any_instance_of(TestClient::ResponseHandler).to receive(:retry_request).and_return(bad_response)
29
27
  object_response = client.get_some_object(some_id: '123')
30
28
 
31
- object_response.on_error do |page, response|
32
- raise StandardError, "Something Bad Happened"
29
+ object_response.on_error do |_page, _response|
30
+ raise StandardError, 'Something Bad Happened'
33
31
  end
34
32
 
35
- expect{object_response.response}.to raise_error(
33
+ expect { object_response.response }.to raise_error(
36
34
  StandardError,
37
- "Something Bad Happened"
35
+ 'Something Bad Happened'
38
36
  )
39
37
  end
40
38
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'api_client_builder/response'
3
2
 
4
3
  module APIClientBuilder
5
4
  describe Response do
@@ -18,7 +17,7 @@ module APIClientBuilder
18
17
 
19
18
  it 'returns false when the response is otherwise marked as failed' do
20
19
  page = Response.new([], 200, [200])
21
- page.mark_failed "Something happened"
20
+ page.mark_failed 'Something happened'
22
21
 
23
22
  expect(page.success?).to eq(false)
24
23
  end
@@ -1,6 +1,5 @@
1
- require 'api_client_builder/api_client'
2
- require 'lib/api_client_builder/test_client/response_handler'
3
- require 'lib/api_client_builder/test_client/http_client_handler'
1
+ require_relative 'response_handler'
2
+ require_relative 'http_client_handler'
4
3
 
5
4
  module TestClient
6
5
  class Client < APIClientBuilder::APIClient
@@ -4,7 +4,6 @@ module TestClient
4
4
  @domain = domain
5
5
  end
6
6
 
7
- def get(route, params = nil, headers = {})
8
- end
7
+ def get(route, params = nil, headers = {}); end
9
8
  end
10
9
  end
@@ -1,36 +1,33 @@
1
- require 'api_client_builder/response'
2
-
3
1
  module TestClient
4
2
  class ResponseHandler
5
3
  SUCCESS_STATUS = 200
6
- SUCCESS_RANGE = [200]
4
+ SUCCESS_RANGE = [200].freeze
7
5
  MAX_RETRIES = 4
8
6
 
9
- def initialize(client, start_url, type, **opts)
7
+ def initialize(_client, _start_url, _type, **_opts)
10
8
  @retries = 0
11
9
  end
12
10
 
13
11
  def get_first_page
14
12
  @current_page = 0
15
- APIClientBuilder::Response.new([1,2,3], SUCCESS_STATUS, SUCCESS_RANGE)
13
+ APIClientBuilder::Response.new([1, 2, 3], SUCCESS_STATUS, SUCCESS_RANGE)
16
14
  end
17
15
 
18
16
  def get_next_page
19
17
  @current_page += 1
20
- APIClientBuilder::Response.new([4,5,6], SUCCESS_STATUS, SUCCESS_RANGE)
18
+ APIClientBuilder::Response.new([4, 5, 6], SUCCESS_STATUS, SUCCESS_RANGE)
21
19
  end
22
20
 
23
- def put_request(body)
21
+ def put_request(_body)
24
22
  APIClientBuilder::Response.new('good request', SUCCESS_STATUS, SUCCESS_RANGE)
25
23
  end
26
24
 
27
- def post_request(body)
25
+ def post_request(_body)
28
26
  APIClientBuilder::Response.new('good request', SUCCESS_STATUS, SUCCESS_RANGE)
29
27
  end
30
28
 
31
29
  def more_pages?
32
- return false if @current_page >= 2
33
- return true
30
+ @current_page < 2
34
31
  end
35
32
 
36
33
  def retryable?(status_code)
@@ -38,10 +35,8 @@ module TestClient
38
35
  status_code != 400 && @retries < MAX_RETRIES
39
36
  end
40
37
 
41
- def retry_request
42
- end
38
+ def retry_request; end
43
39
 
44
- def reset_retries
45
- end
40
+ def reset_retries; end
46
41
  end
47
42
  end
@@ -1,12 +1,11 @@
1
1
  require 'spec_helper'
2
- require 'api_client_builder/url_generator'
3
2
 
4
3
  module APIClientBuilder
5
4
  describe URLGenerator do
6
5
  describe '#build_route' do
7
6
  context 'route with colon params and matching keys' do
8
7
  it 'replaces to route keys with their respective values' do
9
- url_generator = URLGenerator.new("https://www.domain.com/api/endpoints/")
8
+ url_generator = URLGenerator.new('https://www.domain.com/api/endpoints/')
10
9
 
11
10
  route = url_generator.build_route(
12
11
  'object_one/:object_one_id/:object_one_id/route_to_object/:other_object_id/object',
@@ -20,12 +19,14 @@ module APIClientBuilder
20
19
 
21
20
  context 'route with colon params and non matching keys' do
22
21
  it 'raises an argument error' do
23
- url_generator = URLGenerator.new("https://www.domain.com/api/endpoints/")
22
+ url_generator = URLGenerator.new('https://www.domain.com/api/endpoints/')
24
23
 
25
- expect{url_generator.build_route(
26
- 'object_one/:object_one_id/:object_one_id/route_to_object/:other_object_id/object',
27
- other_object_id: '10'
28
- )}.to raise_error(ArgumentError, "Param :object_one_id is required")
24
+ expect do
25
+ url_generator.build_route(
26
+ 'object_one/:object_one_id/:object_one_id/route_to_object/:other_object_id/object',
27
+ other_object_id: '10'
28
+ )
29
+ end.to raise_error(ArgumentError, 'Param :object_one_id is required')
29
30
  end
30
31
  end
31
32
  end
@@ -1,4 +1,10 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter 'lib/api_client_builder/version.rb'
4
+ add_filter 'spec'
5
+ track_files 'lib/**/*.rb'
6
+ end
7
+ SimpleCov.minimum_coverage(97)
8
+
1
9
  require 'bundler/setup'
2
10
  require 'api_client_builder'
3
-
4
- SPEC_DIR = File.dirname(__FILE__)
metadata CHANGED
@@ -1,77 +1,90 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_client_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jayce Higgins
8
+ - Bryan Petty
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2017-06-01 00:00:00.000000000 Z
12
+ date: 2018-06-26 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: pry
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - '>='
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
20
  version: '0'
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - '>='
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
27
  version: '0'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rspec
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - '>='
32
+ - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '0'
34
+ version: '3.7'
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - '>='
39
+ - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '0'
41
+ version: '3.7'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rubocop
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.57.2
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.57.2
41
56
  - !ruby/object:Gem::Dependency
42
- name: wwtd
57
+ name: simplecov
43
58
  requirement: !ruby/object:Gem::Requirement
44
59
  requirements:
45
- - - '>='
60
+ - - "~>"
46
61
  - !ruby/object:Gem::Version
47
62
  version: '0'
48
63
  type: :development
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
- - - '>='
67
+ - - "~>"
53
68
  - !ruby/object:Gem::Version
54
69
  version: '0'
55
70
  description: API Client Builder provides an easy to use interface for creating HTTP
56
71
  api clients
57
72
  email:
58
73
  - jhiggins@instructure.com
74
+ - bpetty@instructure.com
59
75
  - eng@instructure.com
60
76
  executables: []
61
77
  extensions: []
62
78
  extra_rdoc_files: []
63
79
  files:
64
- - .dockerignore
65
- - .gitignore
66
- - .travis.yml
67
- - Dockerfile
80
+ - ".gitignore"
81
+ - ".rubocop.yml"
82
+ - ".travis.yml"
68
83
  - Gemfile
69
84
  - LICENSE.txt
70
85
  - README.md
71
- - api_client_builder-1.0.0.gem
72
86
  - api_client_builder.gemspec
73
87
  - build.sh
74
- - docker-compose.yml
75
88
  - lib/api_client_builder.rb
76
89
  - lib/api_client_builder/api_client.rb
77
90
  - lib/api_client_builder/get_collection_request.rb
@@ -94,7 +107,7 @@ files:
94
107
  - spec/lib/api_client_builder/test_client/response_handler.rb
95
108
  - spec/lib/api_client_builder/url_generator_spec.rb
96
109
  - spec/spec_helper.rb
97
- homepage:
110
+ homepage: https://github.com/instructure/api-client-builder
98
111
  licenses:
99
112
  - MIT
100
113
  metadata: {}
@@ -104,17 +117,17 @@ require_paths:
104
117
  - lib
105
118
  required_ruby_version: !ruby/object:Gem::Requirement
106
119
  requirements:
107
- - - '>='
120
+ - - ">="
108
121
  - !ruby/object:Gem::Version
109
- version: '2.0'
122
+ version: '2.3'
110
123
  required_rubygems_version: !ruby/object:Gem::Requirement
111
124
  requirements:
112
- - - '>='
125
+ - - ">="
113
126
  - !ruby/object:Gem::Version
114
127
  version: '0'
115
128
  requirements: []
116
129
  rubyforge_project:
117
- rubygems_version: 2.0.14
130
+ rubygems_version: 2.5.1
118
131
  signing_key:
119
132
  specification_version: 4
120
133
  summary: API Client Builder provides an easy to use interface for creating HTTP api
@@ -1 +0,0 @@
1
- Gemfile.lock
data/Dockerfile DELETED
@@ -1,16 +0,0 @@
1
- FROM instructure/rvm
2
- MAINTAINER Instructure
3
-
4
- COPY Gemfile* *.gemspec /usr/src/app/
5
- COPY lib/api_client_builder/version.rb /usr/src/app/lib/api_client_builder/
6
-
7
- USER root
8
- RUN chown -R docker:docker /usr/src/app
9
- USER docker
10
- RUN /bin/bash -l -c "cd /usr/src/app && bundle install"
11
-
12
- COPY . /usr/src/app
13
- USER root
14
- RUN chown -R docker:docker /usr/src/app/*
15
- USER docker
16
- CMD /bin/bash -l -c "cd /usr/src/app && pwd && bundle exec wwtd --parallel"
Binary file
@@ -1,4 +0,0 @@
1
- test:
2
- build: .
3
- volumes:
4
- - "coverage:/app/coverage"