api_adaptor 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15a3973e6718c891d082915a0306fec878eaadbaaad013a25dcaba91ce0cb92f
4
- data.tar.gz: d8da61b6f522276dcd74d569673bb6d4a0dd899ab43f9cb1ad85a85eec303c28
3
+ metadata.gz: d434d1287d28256b67543919c32dba816a5c6a682247108a985eee72ac7ca86c
4
+ data.tar.gz: e386558347941960b7c54bbd0107381202bfcf4c8318c0ac3908cf2bd3e1c99a
5
5
  SHA512:
6
- metadata.gz: 24586320847f202c0913f4612a246c2e9e8fef9a380090b773101a8c9fd2204811051c9551fbd7a9c76ab6e25cea655185c213735f937e7a9278b30e120fbc54
7
- data.tar.gz: 8c884ad4796aa32f2623c07d58aa15b8727f5b8dc22549fac2e7a9e2d61849643ce9059fb56edc3cc42c0f8ae0d19389377b20083d34afdf301e72f263c2f899
6
+ metadata.gz: 3ee873a96fa726a95caf41861a683abc276571b3a6424ae44f7ede1c0cc27e242de879b7f8f73930f10c0347d60ff6d31595ba55235a5be1a39e36208359e524
7
+ data.tar.gz: 0a42e0ded563c8f1b9cab2433c8f3f5ca5160da8df923deb80382ecb3736012fa0a136d53799b4681011f6723c18eceaf5fd9e3e2ee853071ca4d38a9903b1ba
data/.rubocop.yml CHANGED
@@ -11,3 +11,12 @@ Style/StringLiteralsInInterpolation:
11
11
 
12
12
  Layout/LineLength:
13
13
  Max: 120
14
+
15
+ Metrics:
16
+ Enabled: false
17
+
18
+ Style/Documentation:
19
+ Enabled: false
20
+
21
+ Layout/LineLength:
22
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,43 +1,47 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- api_adaptor (0.0.0)
4
+ api_adaptor (0.0.2)
5
5
  addressable (~> 2.8)
6
+ link_header (~> 0.0.8)
6
7
  rest-client (~> 2.1)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
11
- addressable (2.8.4)
12
+ addressable (2.8.6)
12
13
  public_suffix (>= 2.0.2, < 6.0)
13
14
  ast (2.4.2)
14
15
  crack (0.4.5)
15
16
  rexml
16
17
  diff-lcs (1.5.0)
17
- domain_name (0.5.20190701)
18
- unf (>= 0.0.5, < 1.0.0)
19
- hashdiff (1.0.1)
18
+ domain_name (0.6.20240107)
19
+ hashdiff (1.1.0)
20
20
  http-accept (1.7.0)
21
21
  http-cookie (1.0.5)
22
22
  domain_name (~> 0.5)
23
- json (2.6.3)
24
- mime-types (3.4.1)
23
+ json (2.7.1)
24
+ language_server-protocol (3.17.0.3)
25
+ link_header (0.0.8)
26
+ mime-types (3.5.2)
25
27
  mime-types-data (~> 3.2015)
26
- mime-types-data (3.2023.0218.1)
28
+ mime-types-data (3.2023.1205)
27
29
  netrc (0.11.0)
28
- parallel (1.23.0)
29
- parser (3.2.2.1)
30
+ parallel (1.24.0)
31
+ parser (3.3.0.3)
30
32
  ast (~> 2.4.1)
31
- public_suffix (5.0.1)
33
+ racc
34
+ public_suffix (5.0.4)
35
+ racc (1.7.3)
32
36
  rainbow (3.1.1)
33
- rake (13.0.6)
34
- regexp_parser (2.8.0)
37
+ rake (13.1.0)
38
+ regexp_parser (2.9.0)
35
39
  rest-client (2.1.0)
36
40
  http-accept (>= 1.7.0, < 2.0)
37
41
  http-cookie (>= 1.0.2, < 2.0)
38
42
  mime-types (>= 1.16, < 4.0)
39
43
  netrc (~> 0.8)
40
- rexml (3.2.5)
44
+ rexml (3.2.6)
41
45
  rspec (3.12.0)
42
46
  rspec-core (~> 3.12.0)
43
47
  rspec-expectations (~> 3.12.0)
@@ -47,29 +51,27 @@ GEM
47
51
  rspec-expectations (3.12.3)
48
52
  diff-lcs (>= 1.2.0, < 2.0)
49
53
  rspec-support (~> 3.12.0)
50
- rspec-mocks (3.12.5)
54
+ rspec-mocks (3.12.6)
51
55
  diff-lcs (>= 1.2.0, < 2.0)
52
56
  rspec-support (~> 3.12.0)
53
- rspec-support (3.12.0)
54
- rubocop (1.51.0)
57
+ rspec-support (3.12.1)
58
+ rubocop (1.59.0)
55
59
  json (~> 2.3)
60
+ language_server-protocol (>= 3.17.0)
56
61
  parallel (~> 1.10)
57
- parser (>= 3.2.0.0)
62
+ parser (>= 3.2.2.4)
58
63
  rainbow (>= 2.2.2, < 4.0)
59
64
  regexp_parser (>= 1.8, < 3.0)
60
65
  rexml (>= 3.2.5, < 4.0)
61
- rubocop-ast (>= 1.28.0, < 2.0)
66
+ rubocop-ast (>= 1.30.0, < 2.0)
62
67
  ruby-progressbar (~> 1.7)
63
68
  unicode-display_width (>= 2.4.0, < 3.0)
64
- rubocop-ast (1.28.1)
69
+ rubocop-ast (1.30.0)
65
70
  parser (>= 3.2.1.0)
66
71
  ruby-progressbar (1.13.0)
67
- timecop (0.9.6)
68
- unf (0.1.4)
69
- unf_ext
70
- unf_ext (0.0.8.2)
71
- unicode-display_width (2.4.2)
72
- webmock (3.18.1)
72
+ timecop (0.9.8)
73
+ unicode-display_width (2.5.0)
74
+ webmock (3.19.1)
73
75
  addressable (>= 2.8.0)
74
76
  crack (>= 0.3.2)
75
77
  hashdiff (>= 0.4.0, < 2.0.0)
data/README.md CHANGED
@@ -7,17 +7,21 @@ Intended to bootstrap the quick writing of Adaptors for specific APIs, without h
7
7
 
8
8
  Install the gem and add to the application's Gemfile by executing:
9
9
 
10
- $ bundle add api_adaptor
10
+ ```shell
11
+ bundle add api_adaptor
12
+ ```
11
13
 
12
14
  If bundler is not being used to manage dependencies, install the gem by executing:
13
15
 
14
- $ gem install api_adaptor
16
+ ```shell
17
+ gem install api_adaptor
18
+ ```
15
19
 
16
20
  ## Usage
17
21
 
18
22
  Use the ApiAdaptor as a base class for your API wrapper, for example:
19
23
 
20
- ```
24
+ ```ruby
21
25
  class MyApi < ApiAdaptor::Base
22
26
  def base_url
23
27
  endpoint
@@ -29,46 +33,46 @@ Use your new class to create a client that can make HTTP requests to JSON APIs f
29
33
 
30
34
  ### GET JSON
31
35
 
32
- ```
33
- client = MyApi.new
34
- response = client.get_json("http://some.endpoint/json")
36
+ ```ruby
37
+ client = MyApi.new
38
+ response = client.get_json("http://some.endpoint/json")
35
39
  ```
36
40
 
37
41
  ### POST JSON
38
42
 
39
- ```
40
- client = MyApi.new
41
- response = client.post_json("http://some.endpoint/json", { "foo": "bar" })
43
+ ```ruby
44
+ client = MyApi.new
45
+ response = client.post_json("http://some.endpoint/json", { "foo": "bar" })
42
46
  ```
43
47
 
44
48
  ### PUT JSON
45
49
 
46
- ```
47
- client = MyApi.new
48
- response = client.put_json("http://some.endpoint/json", { "foo": "bar" })
50
+ ```ruby
51
+ client = MyApi.new
52
+ response = client.put_json("http://some.endpoint/json", { "foo": "bar" })
49
53
  ```
50
54
 
51
55
  ### PATCH JSON
52
56
 
53
- ```
54
- client = MyApi.new
55
- response = client.patch_json("http://some.endpoint/json", { "foo": "bar" })
57
+ ```ruby
58
+ client = MyApi.new
59
+ response = client.patch_json("http://some.endpoint/json", { "foo": "bar" })
56
60
  ```
57
61
 
58
62
  ### DELETE JSON
59
63
 
60
- ```
61
- client = MyApi.new
62
- response = client.delete_json("http://some.endpoint/json", { "foo": "bar" })
64
+ ```ruby
65
+ client = MyApi.new
66
+ response = client.delete_json("http://some.endpoint/json", { "foo": "bar" })
63
67
  ```
64
68
 
65
69
  ### GET raw requests
66
70
 
67
71
  you can also get a raw response from the API
68
72
 
69
- ```
70
- client = MyApi.new
71
- response = client.get_raw("http://some.endpoint/json")
73
+ ```ruby
74
+ client = MyApi.new
75
+ response = client.get_raw("http://some.endpoint/json")
72
76
  ```
73
77
 
74
78
  ## Environment variables
@@ -77,20 +81,22 @@ User Agent is populated with a default string.
77
81
  See .env.example.
78
82
 
79
83
  For instance if you provide:
80
- ```
84
+
85
+ ```bash
81
86
  APP_NAME=test_app
82
87
  APP_VERSION=1.0.0
83
88
  APP_CONTACT=contact@example.com
84
89
  ```
85
90
 
86
91
  User agent would read
87
- ```
92
+
93
+ ```text
88
94
  test_app/1.0.0 (contact@example.com)
89
95
  ```
90
96
 
91
97
  ## Contributing
92
98
 
93
- Bug reports and pull requests are welcome on GitHub at https://github.com/huwd/api_adaptor. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/huwd/api_adaptor/blob/main/CODE_OF_CONDUCT.md).
99
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/huwd/api_adaptor>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/huwd/api_adaptor/blob/main/CODE_OF_CONDUCT.md).
94
100
 
95
101
  ## License
96
102
 
@@ -1,86 +1,90 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "json_client"
2
4
  require "cgi"
3
5
  require_relative "null_logger"
4
6
  require_relative "list_response"
5
7
 
6
- class ApiAdaptor::Base
7
- class InvalidAPIURL < StandardError
8
- end
8
+ module ApiAdaptor
9
+ class Base
10
+ class InvalidAPIURL < StandardError
11
+ end
9
12
 
10
- extend Forwardable
13
+ extend Forwardable
11
14
 
12
- def client
13
- @client ||= create_client
14
- end
15
+ def client
16
+ @client ||= create_client
17
+ end
15
18
 
16
- def create_client
17
- ApiAdaptor::JsonClient.new(options)
18
- end
19
+ def create_client
20
+ ApiAdaptor::JsonClient.new(options)
21
+ end
19
22
 
20
- def_delegators :client,
21
- :get_json,
22
- :post_json,
23
- :put_json,
24
- :patch_json,
25
- :delete_json,
26
- :get_raw,
27
- :get_raw!,
28
- :put_multipart,
29
- :post_multipart
30
-
31
- attr_reader :options
32
-
33
- class << self
34
- attr_writer :logger
35
- attr_accessor :default_options
36
- end
23
+ def_delegators :client,
24
+ :get_json,
25
+ :post_json,
26
+ :put_json,
27
+ :patch_json,
28
+ :delete_json,
29
+ :get_raw,
30
+ :get_raw!,
31
+ :put_multipart,
32
+ :post_multipart
33
+
34
+ attr_reader :options
35
+
36
+ class << self
37
+ attr_writer :logger
38
+ attr_accessor :default_options
39
+ end
37
40
 
38
- def self.logger
39
- @logger ||= ApiAdaptor::NullLogger.new
40
- end
41
+ def self.logger
42
+ @logger ||= ApiAdaptor::NullLogger.new
43
+ end
41
44
 
42
- def initialize(endpoint_url, options = {})
43
- options[:endpoint_url] = endpoint_url
44
- raise InvalidAPIURL unless endpoint_url =~ URI::RFC3986_Parser::RFC3986_URI
45
+ def initialize(endpoint_url, options = {})
46
+ options[:endpoint_url] = endpoint_url
47
+ raise InvalidAPIURL unless endpoint_url =~ URI::RFC3986_Parser::RFC3986_URI
45
48
 
46
- base_options = { logger: ApiAdaptor::Base.logger }
47
- default_options = base_options.merge(ApiAdaptor::Base.default_options || {})
48
- @options = default_options.merge(options)
49
- self.endpoint = options[:endpoint_url]
50
- end
49
+ base_options = { logger: ApiAdaptor::Base.logger }
50
+ default_options = base_options.merge(ApiAdaptor::Base.default_options || {})
51
+ @options = default_options.merge(options)
52
+ self.endpoint = options[:endpoint_url]
53
+ end
51
54
 
52
- def url_for_slug(slug, options = {})
53
- "#{base_url}/#{slug}.json#{query_string(options)}"
54
- end
55
+ def url_for_slug(slug, options = {})
56
+ "#{base_url}/#{slug}.json#{query_string(options)}"
57
+ end
55
58
 
56
- def get_list(url)
57
- get_json(url) do |r|
58
- ApiAdaptor::ListResponse.new(r, self)
59
+ def get_list(url)
60
+ get_json(url) do |r|
61
+ ApiAdaptor::ListResponse.new(r, self)
62
+ end
59
63
  end
60
- end
61
64
 
62
- private
65
+ private
63
66
 
64
- attr_accessor :endpoint
67
+ attr_accessor :endpoint
65
68
 
66
- def query_string(params)
67
- return "" if params.empty?
69
+ def query_string(params)
70
+ return "" if params.empty?
68
71
 
69
- param_pairs = params.sort.map { |key, value|
70
- case value
71
- when Array
72
- value.map do |v|
73
- "#{CGI.escape("#{key}[]")}=#{CGI.escape(v.to_s)}"
72
+ param_pairs = params.sort.map do |key, value|
73
+ case value
74
+ when Array
75
+ value.map do |v|
76
+ "#{CGI.escape("#{key}[]")}=#{CGI.escape(v.to_s)}"
77
+ end
78
+ else
79
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
74
80
  end
75
- else
76
- "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
77
- end
78
- }.flatten
81
+ end.flatten
79
82
 
80
- "?#{param_pairs.join('&')}"
81
- end
83
+ "?#{param_pairs.join("&")}"
84
+ end
82
85
 
83
- def uri_encode(param)
84
- Addressable::URI.encode(param.to_s)
86
+ def uri_encode(param)
87
+ Addressable::URI.encode(param.to_s)
88
+ end
85
89
  end
86
- end
90
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApiAdaptor
2
4
  # Abstract error class
3
5
  class BaseError < StandardError; end
@@ -102,4 +104,4 @@ module ApiAdaptor
102
104
  end
103
105
  end
104
106
  end
105
- end
107
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApiAdaptor
2
4
  class Headers
3
5
  class << self
@@ -6,18 +8,18 @@ module ApiAdaptor
6
8
  end
7
9
 
8
10
  def headers
9
- header_data.reject { |_k, v| (v.nil? || v.empty?) }
11
+ header_data.reject { |_k, v| v.nil? || v.empty? }
10
12
  end
11
13
 
12
14
  def clear_headers
13
15
  Thread.current[:headers] = {}
14
16
  end
15
17
 
16
- private
18
+ private
17
19
 
18
20
  def header_data
19
21
  Thread.current[:headers] ||= {}
20
22
  end
21
23
  end
22
24
  end
23
- end
25
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "exceptions"
2
4
  require_relative "variables"
3
5
  require_relative "null_logger"
@@ -13,9 +15,7 @@ module ApiAdaptor
13
15
  attr_accessor :logger, :options
14
16
 
15
17
  def initialize(options = {})
16
- if options[:disable_timeout] || options[:timeout].to_i.negative?
17
- raise "It is no longer possible to disable the timeout."
18
- end
18
+ raise "It is no longer possible to disable the timeout." if options[:disable_timeout] || options[:timeout].to_i.negative?
19
19
 
20
20
  @logger = options[:logger] || NullLogger.new
21
21
  @options = options
@@ -24,7 +24,7 @@ module ApiAdaptor
24
24
  def self.default_request_headers
25
25
  {
26
26
  "Accept" => "application/json",
27
- "User-Agent" => "#{Variables.app_name}/#{Variables.app_version} (#{Variables. app_contact}",
27
+ "User-Agent" => "#{Variables.app_name}/#{Variables.app_version} (#{Variables.app_contact})"
28
28
  }
29
29
  end
30
30
 
@@ -34,7 +34,7 @@ module ApiAdaptor
34
34
 
35
35
  def self.json_body_headers
36
36
  {
37
- "Content-Type" => "application/json",
37
+ "Content-Type" => "application/json"
38
38
  }
39
39
  end
40
40
 
@@ -78,7 +78,7 @@ module ApiAdaptor
78
78
  Response.new(r)
79
79
  end
80
80
 
81
- private
81
+ private
82
82
 
83
83
  def do_raw_request(method, url, params = nil)
84
84
  do_request(method, url, params)
@@ -94,9 +94,7 @@ module ApiAdaptor
94
94
  # from the Net::HTTPResponse
95
95
  def do_json_request(method, url, params = nil, additional_headers = {}, &create_response)
96
96
  begin
97
- if params
98
- additional_headers.merge!(self.class.json_body_headers)
99
- end
97
+ additional_headers.merge!(self.class.json_body_headers) if params
100
98
  response = do_request(method, url, (params.to_json if params), additional_headers)
101
99
  rescue RestClient::Exception => e
102
100
  # Attempt to parse the body as JSON if possible
@@ -119,25 +117,24 @@ module ApiAdaptor
119
117
  if @options[:bearer_token]
120
118
  headers = method_params[:headers] || {}
121
119
  method_params.merge(headers: headers.merge(
122
- "Authorization" => "Bearer #{@options[:bearer_token]}",
120
+ "Authorization" => "Bearer #{@options[:bearer_token]}"
123
121
  ))
124
122
  elsif @options[:basic_auth]
125
123
  method_params.merge(
126
124
  user: @options[:basic_auth][:user],
127
- password: @options[:basic_auth][:password],
125
+ password: @options[:basic_auth][:password]
128
126
  )
129
127
  else
130
128
  method_params
131
129
  end
132
130
  end
133
131
 
134
-
135
132
  # Take a hash of parameters for Request#execute; return a hash of
136
133
  # parameters with timeouts included
137
134
  def with_timeout(method_params)
138
135
  method_params.merge(
139
136
  timeout: options[:timeout] || DEFAULT_TIMEOUT_IN_SECONDS,
140
- open_timeout: options[:timeout] || DEFAULT_TIMEOUT_IN_SECONDS,
137
+ open_timeout: options[:timeout] || DEFAULT_TIMEOUT_IN_SECONDS
141
138
  )
142
139
  end
143
140
 
@@ -146,14 +143,14 @@ module ApiAdaptor
146
143
  headers: default_headers
147
144
  .merge(method_params[:headers] || {})
148
145
  .merge(ApiAdaptor::Headers.headers)
149
- .merge(additional_headers),
146
+ .merge(additional_headers)
150
147
  )
151
148
  end
152
149
 
153
150
  def with_ssl_options(method_params)
154
151
  method_params.merge(
155
152
  # This is the default value anyway, but we should probably be explicit
156
- verify_ssl: OpenSSL::SSL::VERIFY_NONE,
153
+ verify_ssl: OpenSSL::SSL::VERIFY_NONE
157
154
  )
158
155
  end
159
156
 
@@ -164,26 +161,27 @@ module ApiAdaptor
164
161
 
165
162
  method_params = {
166
163
  method: method,
167
- url: url,
164
+ url: url
168
165
  }
169
166
 
170
167
  method_params[:payload] = params
171
168
  method_params = with_timeout(method_params)
172
169
  method_params = with_headers(method_params, self.class.default_request_headers, additional_headers)
173
170
  method_params = with_auth_options(method_params)
174
- if URI.parse(url).is_a? URI::HTTPS
175
- method_params = with_ssl_options(method_params)
176
- end
171
+ method_params = with_ssl_options(method_params) if URI.parse(url).is_a? URI::HTTPS
177
172
 
178
173
  ::RestClient::Request.execute(method_params)
179
174
  rescue Errno::ECONNREFUSED => e
180
- logger.error loggable.merge(status: "refused", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
175
+ logger.error loggable.merge(status: "refused", error_message: e.message, error_class: e.class.name,
176
+ end_time: Time.now.to_f).to_json
181
177
  raise ApiAdaptor::EndpointNotFound, "Could not connect to #{url}"
182
178
  rescue RestClient::Exceptions::Timeout => e
183
- logger.error loggable.merge(status: "timeout", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
179
+ logger.error loggable.merge(status: "timeout", error_message: e.message, error_class: e.class.name,
180
+ end_time: Time.now.to_f).to_json
184
181
  raise ApiAdaptor::TimedOutException, e.message
185
182
  rescue URI::InvalidURIError => e
186
- logger.error loggable.merge(status: "invalid_uri", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
183
+ logger.error loggable.merge(status: "invalid_uri", error_message: e.message, error_class: e.class.name,
184
+ end_time: Time.now.to_f).to_json
187
185
  raise ApiAdaptor::InvalidUrl, e.message
188
186
  rescue RestClient::Exception => e
189
187
  # Log the error here, since we have access to loggable, but raise the
@@ -192,10 +190,12 @@ module ApiAdaptor
192
190
  logger.warn loggable.to_json
193
191
  raise
194
192
  rescue Errno::ECONNRESET => e
195
- logger.error loggable.merge(status: "connection_reset", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
193
+ logger.error loggable.merge(status: "connection_reset", error_message: e.message, error_class: e.class.name,
194
+ end_time: Time.now.to_f).to_json
196
195
  raise ApiAdaptor::TimedOutException, e.message
197
196
  rescue SocketError => e
198
- logger.error loggable.merge(status: "socket_error", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
197
+ logger.error loggable.merge(status: "socket_error", error_message: e.message, error_class: e.class.name,
198
+ end_time: Time.now.to_f).to_json
199
199
  raise ApiAdaptor::SocketErrorException, e.message
200
200
  end
201
201
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
  require "api_adaptor/response"
3
5
  require "link_header"
@@ -24,7 +26,7 @@ module ApiAdaptor
24
26
  to_hash["results"]
25
27
  end
26
28
 
27
- def has_next_page?
29
+ def next_page?
28
30
  !page_link("next").nil?
29
31
  end
30
32
 
@@ -33,20 +35,16 @@ module ApiAdaptor
33
35
  # avoid us making multiple requests for the same page, but we shouldn't
34
36
  # allow the data to change once it's already been loaded, so long as we
35
37
  # retain a reference to any one page in the sequence
36
- @next_page ||= if has_next_page?
37
- @api_client.get_list page_link("next").href
38
- end
38
+ @next_page ||= (@api_client.get_list page_link("next").href if next_page?)
39
39
  end
40
40
 
41
- def has_previous_page?
41
+ def previous_page?
42
42
  !page_link("previous").nil?
43
43
  end
44
44
 
45
45
  def previous_page
46
46
  # See the note in `next_page` for why this is memoised
47
- @previous_page ||= if has_previous_page?
48
- @api_client.get_list(page_link("previous").href)
49
- end
47
+ @previous_page ||= (@api_client.get_list(page_link("previous").href) if previous_page?)
50
48
  end
51
49
 
52
50
  # Transparently get all results across all pages. Compare this with #each
@@ -70,13 +68,11 @@ module ApiAdaptor
70
68
  def with_subsequent_pages
71
69
  Enumerator.new do |yielder|
72
70
  each { |i| yielder << i }
73
- if has_next_page?
74
- next_page.with_subsequent_pages.each { |i| yielder << i }
75
- end
71
+ next_page.with_subsequent_pages.each { |i| yielder << i } if next_page?
76
72
  end
77
73
  end
78
74
 
79
- private
75
+ private
80
76
 
81
77
  def link_header
82
78
  @link_header ||= LinkHeader.parse @http_response.headers[:link]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
  require "forwardable"
3
5
 
@@ -20,7 +22,7 @@ module ApiAdaptor
20
22
  include Enumerable
21
23
 
22
24
  class CacheControl < Hash
23
- PATTERN = /([-a-z]+)(?:\s*=\s*([^,\s]+))?,?+/i
25
+ PATTERN = /([-a-z]+)(?:\s*=\s*([^,\s]+))?,?+/i.freeze
24
26
 
25
27
  def initialize(value = nil)
26
28
  super()
@@ -58,12 +60,12 @@ module ApiAdaptor
58
60
  def reverse_max_age
59
61
  self["r-maxage"].to_i if key?("r-maxage")
60
62
  end
61
- alias_method :r_maxage, :reverse_max_age
63
+ alias r_maxage reverse_max_age
62
64
 
63
65
  def shared_max_age
64
66
  self["s-maxage"].to_i if key?("r-maxage")
65
67
  end
66
- alias_method :s_maxage, :shared_max_age
68
+ alias s_maxage shared_max_age
67
69
 
68
70
  def to_s
69
71
  directives = []
@@ -152,7 +154,7 @@ module ApiAdaptor
152
154
  false
153
155
  end
154
156
 
155
- private
157
+ private
156
158
 
157
159
  def transform_parsed(value)
158
160
  return value if @web_urls_relative_to.nil?
@@ -180,4 +182,4 @@ module ApiAdaptor
180
182
  end
181
183
  end
182
184
  end
183
- end
185
+ end
@@ -1,15 +1,17 @@
1
- module ApiAdaptor
2
- module Variables
3
- def self.app_name
4
- ENV['APP_NAME'] || "Ruby ApiAdaptor App"
5
- end
1
+ # frozen_string_literal: true
6
2
 
7
- def self.app_version
8
- ENV['APP_VERSION'] || "Version not stated"
9
- end
3
+ module ApiAdaptor
4
+ module Variables
5
+ def self.app_name
6
+ ENV["APP_NAME"] || "Ruby ApiAdaptor App"
7
+ end
8
+
9
+ def self.app_version
10
+ ENV["APP_VERSION"] || "Version not stated"
11
+ end
10
12
 
11
- def self.app_contact
12
- ENV['APP_CONTACT'] || "Contact not stated"
13
- end
13
+ def self.app_contact
14
+ ENV["APP_CONTACT"] || "Contact not stated"
14
15
  end
15
- end
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApiAdaptor
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  end
metadata CHANGED
@@ -1,127 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_adaptor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Huw Diprose
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-02 00:00:00.000000000 Z
11
+ date: 2024-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rest-client
14
+ name: addressable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.1'
19
+ version: '2.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.1'
26
+ version: '2.8'
27
27
  - !ruby/object:Gem::Dependency
28
- name: addressable
28
+ name: link_header
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.8'
33
+ version: 0.0.8
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.8'
40
+ version: 0.0.8
41
41
  - !ruby/object:Gem::Dependency
42
- name: link_header
42
+ name: rest-client
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.0.8
47
+ version: '2.1'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.0.8
54
+ version: '2.1'
55
55
  - !ruby/object:Gem::Dependency
56
- name: webmock
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.18'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.18'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: timecop
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0.9'
75
+ version: '3.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.9'
82
+ version: '3.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '13.0'
89
+ version: '1.21'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '13.0'
96
+ version: '1.21'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rspec
98
+ name: timecop
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '3.0'
103
+ version: '0.9'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '3.0'
110
+ version: '0.9'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rubocop
112
+ name: webmock
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1.21'
117
+ version: '3.18'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1.21'
124
+ version: '3.18'
125
125
  description: A basic adaptor to send HTTP requests and parse the responses. Intended
126
126
  to bootstrap the quick writing of Adaptors for specific APIs, without having to
127
127
  write the same old JSON request and processing time and time again.