wrappi 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -2
- data/README.md +260 -30
- data/lib/wrappi.rb +3 -0
- data/lib/wrappi/async_handler.rb +17 -0
- data/lib/wrappi/async_job.rb +51 -0
- data/lib/wrappi/client.rb +1 -4
- data/lib/wrappi/endpoint.rb +50 -27
- data/lib/wrappi/version.rb +1 -1
- data/wrappi.gemspec +8 -3
- metadata +16 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d76d08b4ea48473c331491f345bf3349020d2939038abab2df92c6b2ee39a159
|
4
|
+
data.tar.gz: c17875fe3958e459610c7996f285e493f50b589e053703a5a14aefd54c1061d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '03181ab50cbfeb1e55b408bf5d8fd11e919b9e6f6528ff0c4670b1296cac684fc67a0a29b376b292772cde316ed9cfe9a0e50475278c2a5da05946728afed817'
|
7
|
+
data.tar.gz: 289a464e32f98a82c0098e5372e96935377a8ec2c9da5c9f8d3f7c3e55bbc7d33542e51f7fe7c4b565b70fae787a1ee7186b1c95084ef6bb94bef31348f7f1e4
|
data/.travis.yml
CHANGED
@@ -7,11 +7,16 @@ rvm:
|
|
7
7
|
- 2.4.4
|
8
8
|
- 2.5.1
|
9
9
|
- ruby-head
|
10
|
+
matrix:
|
11
|
+
allow_failures:
|
12
|
+
- rvm: 2.3.7
|
13
|
+
- rvm: ruby-head
|
14
|
+
fast_finish: true
|
10
15
|
before_install:
|
11
16
|
- docker build -t dummy -f spec/dummy/Dockerfile .
|
12
|
-
- docker run -d -p 127.0.0.1:9873:9873 dummy
|
17
|
+
- docker run -d -p 127.0.0.1:9873:9873 dummy /bin/sh -c "bin/rails server -b 0.0.0.0 -p 9873"
|
13
18
|
- docker ps -a
|
14
|
-
- gem install bundler
|
19
|
+
- gem install bundler
|
15
20
|
script:
|
16
21
|
- bundle exec rspec
|
17
22
|
# Code climate test reporter
|
data/README.md
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/8751a0b6523a52b5e23e/test_coverage)](https://codeclimate.com/github/arturictus/wrappi/test_coverage)
|
4
4
|
|
5
5
|
# Wrappi
|
6
|
+
Making APIs fun again!
|
6
7
|
|
7
|
-
Framework to create API clients.
|
8
|
-
|
9
|
-
|
8
|
+
Wrappi is a Framework to create API clients. The intention is to bring the best practices and standardize how API clients behave.
|
9
|
+
It allows to create API clients in a declarative way improving readability and unifying the behavior. It abstracts complex operations like caching, retries background requests and error handling.
|
10
|
+
|
11
|
+
Enjoy!
|
10
12
|
|
11
13
|
## Installation
|
12
14
|
|
@@ -29,7 +31,7 @@ Or install it yourself as:
|
|
29
31
|
__Github example:__
|
30
32
|
|
31
33
|
```ruby
|
32
|
-
module
|
34
|
+
module GithubAPI
|
33
35
|
class Client < Wrappi::Client
|
34
36
|
setup do |config|
|
35
37
|
config.domain = 'https://api.github.com'
|
@@ -49,13 +51,191 @@ end
|
|
49
51
|
```
|
50
52
|
|
51
53
|
```ruby
|
52
|
-
user =
|
54
|
+
user = GithubAPI::User.new(username: 'arturictus')
|
53
55
|
user.success? # => true
|
54
56
|
user.error? # => false
|
55
57
|
user.status_code # => 200
|
56
58
|
user.body # => {"login"=>"arturictus", "id"=>1930175, ...}
|
57
59
|
```
|
58
60
|
|
61
|
+
#### Async
|
62
|
+
Wrappi comes with a background Job out of the box. If you are in a Rails app the `#async`
|
63
|
+
method will queue a new job (`< ActiveJob::Base`) that will make the request and trigger the async callback
|
64
|
+
after the request is made.
|
65
|
+
|
66
|
+
example:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class User < Wrappi::Endpoint
|
70
|
+
client Client
|
71
|
+
verb :get
|
72
|
+
path "users/:username"
|
73
|
+
async_callback do |opts|
|
74
|
+
# this will be called in background after the request is made
|
75
|
+
if success?
|
76
|
+
if opts[:create]
|
77
|
+
CreateUserService.call(body)
|
78
|
+
elsif opts[:update]
|
79
|
+
UpdateUserService.call(body)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
# This will execute the request in a background job
|
85
|
+
Github::User.new(username: 'arturictus').async(create: true)
|
86
|
+
```
|
87
|
+
|
88
|
+
If you need to send options to your Job (the `::set` method) you can pass the key `set`
|
89
|
+
to the options.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
Github::User.new(username: 'arturictus').async(create: true, set: { wait: 10.minutes })
|
93
|
+
```
|
94
|
+
|
95
|
+
#### Cache
|
96
|
+
You can enable cache per endpoint.
|
97
|
+
|
98
|
+
Set the cache Handler in your client.
|
99
|
+
It must behave like `Rails.cache` and respond to:
|
100
|
+
- `read([key])`
|
101
|
+
- `write([key, value, options])`
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
class Client < Wrappi::Client
|
105
|
+
setup do |config|
|
106
|
+
config.domain = 'https://api.github.com'
|
107
|
+
config.cache = Rails.cache
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
Enable cache in your endpoint.
|
113
|
+
```ruby
|
114
|
+
class User < Wrappi::Endpoint
|
115
|
+
cache true # enable for endpoint
|
116
|
+
client Client
|
117
|
+
verb :get
|
118
|
+
path "users/:username"
|
119
|
+
end
|
120
|
+
|
121
|
+
user = User.new(username: 'arturictus')
|
122
|
+
user.response.class # => Wrappi::Response
|
123
|
+
user.flush
|
124
|
+
user.response.class # => Wrappi::CachedResponse
|
125
|
+
user.success? # => true
|
126
|
+
user.body # => {"login"=>"arturictus", "id"=>1930175, ...}
|
127
|
+
```
|
128
|
+
|
129
|
+
When cached the response will be a `Wrappi::CachedResponse`. `Wrappi::CachedResponse` behaves
|
130
|
+
like `Wrappi::Response` that means you can use the endpoint in the same way as it was a non cached.
|
131
|
+
See `cache_options` to fine tune your cache with expiration and other cache options.
|
132
|
+
|
133
|
+
You can use options to cache a single request.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
class User < Wrappi::Endpoint
|
137
|
+
client Client
|
138
|
+
verb :get
|
139
|
+
path "users/:username"
|
140
|
+
end
|
141
|
+
User.new({username: 'arturictus'}, cache: true)
|
142
|
+
user.response.class # => Wrappi::Response
|
143
|
+
user.flush
|
144
|
+
user.response.class # => Wrappi::CachedResponse
|
145
|
+
user.success? # => true
|
146
|
+
user.body # => {"login"=>"arturictus", "id"=>1930175, ...}
|
147
|
+
```
|
148
|
+
|
149
|
+
#### Retry
|
150
|
+
Sometimes you want to retry if certain conditions affected your request.
|
151
|
+
|
152
|
+
This will retry if status code is not `200`
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
class User < Wrappi::Endpoint
|
156
|
+
client Client
|
157
|
+
verb :get
|
158
|
+
path "users/:username"
|
159
|
+
retry_if do |response, endpoint|
|
160
|
+
endpoint.status_code != 200
|
161
|
+
end
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
165
|
+
Check more configuration options and examples for `retry_if` and `retry_options` below.
|
166
|
+
|
167
|
+
#### Flexibility
|
168
|
+
|
169
|
+
__options:__
|
170
|
+
|
171
|
+
Pass a second argument with options.
|
172
|
+
```ruby
|
173
|
+
params = { username: 'arturictus' }
|
174
|
+
options = { options_in_my_instance: "yeah!" }
|
175
|
+
|
176
|
+
User.new(params, options)
|
177
|
+
```
|
178
|
+
|
179
|
+
__Dynamic configurations:__
|
180
|
+
|
181
|
+
All the configs in `Endpoint` are evaluated at instance level except: `around_request` and `retry_if` because of their nature.
|
182
|
+
That allows you to fine tune the configuration at a instance level.
|
183
|
+
|
184
|
+
example:
|
185
|
+
|
186
|
+
Right now the default for `cache` config is: `proc { options[:cache] }`.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
class User < Wrappi::Endpoint
|
190
|
+
client Client
|
191
|
+
verb :get
|
192
|
+
path "users/:username"
|
193
|
+
cache do
|
194
|
+
if input_params[:username] == 'arturictus'
|
195
|
+
false
|
196
|
+
else
|
197
|
+
options[:cache]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
```
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
__endpoint is a ruby class:__ :open_mouth:
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
class User < Wrappi::Endpoint
|
209
|
+
client Client
|
210
|
+
verb :get
|
211
|
+
path "users/:username"
|
212
|
+
cache do
|
213
|
+
cache?
|
214
|
+
end
|
215
|
+
|
216
|
+
def cache?
|
217
|
+
if input_params[:username] == 'arturictus'
|
218
|
+
false
|
219
|
+
else
|
220
|
+
options[:cache]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def parsed_response
|
225
|
+
@parsed_response ||= MyParser.new(body)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
__inheritance:__
|
231
|
+
All the configs will be inherited
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
class UserDetail < User
|
235
|
+
path "users/:username/detail"
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
59
239
|
### Configurations
|
60
240
|
|
61
241
|
#### Client
|
@@ -64,28 +244,32 @@ user.body # => {"login"=>"arturictus", "id"=>1930175, ...}
|
|
64
244
|
|-----------------|--------------------------|--------------------------------------------------------------------------|----------|
|
65
245
|
| domain | String | | * |
|
66
246
|
| params | Hash | | |
|
67
|
-
| logger | Logger | Logger.new(STDOUT) | |
|
68
247
|
| headers | Hash | { 'Content-Type' => 'application/json', 'Accept' => 'application/json' } | |
|
69
|
-
|
|
248
|
+
| async_handler | const | Wrappi::AsyncHandler | |
|
249
|
+
| cache | const | | |
|
250
|
+
| logger | Logger | Logger.new(STDOUT) | |
|
251
|
+
| timeout | Hash | { write: 9, connect: 9, read: 9 } | |
|
70
252
|
| use_ssl_context | Boolean | false | |
|
253
|
+
| ssl_context | OpenSSL::SSL::SSLContext | | |
|
71
254
|
|
72
255
|
#### Endpoint
|
73
256
|
|
74
|
-
| Name | Type
|
75
|
-
|
76
|
-
| client | Wrappi::Client
|
77
|
-
| path | String
|
78
|
-
| verb | Symbol
|
79
|
-
| default_params | Hash
|
80
|
-
| headers | Hash
|
81
|
-
| basic_auth | Hash (keys: user, pass)
|
82
|
-
| follow_redirects | Boolean
|
83
|
-
| body_type | Symbol, one of: :json,:form,:body
|
84
|
-
| cache | Boolean
|
85
|
-
| cache_options | Hash
|
86
|
-
| retry_if | block
|
87
|
-
| retry_options | Hash
|
88
|
-
| around_request | block
|
257
|
+
| Name | Type | Default | Required |
|
258
|
+
|------------------|--------------------------------------------|-------------------------|----------|
|
259
|
+
| client | Wrappi::Client | | * |
|
260
|
+
| path | String | | * |
|
261
|
+
| verb | Symbol | :get | * |
|
262
|
+
| default_params | Hash `or` block -> Hash | {} | |
|
263
|
+
| headers | Hash `or` block -> Hash | proc { client.headers } | |
|
264
|
+
| basic_auth | Hash (keys: user, pass) `or` block -> Hash | | |
|
265
|
+
| follow_redirects | Boolean `or` block -> Boolean | true | |
|
266
|
+
| body_type | Symbol, one of: :json,:form,:body | :json | |
|
267
|
+
| cache | Boolean `or` block -> Boolean | proc { options[:cache] }| |
|
268
|
+
| cache_options | Hash `or` block -> Hash | | |
|
269
|
+
| retry_if | block | | |
|
270
|
+
| retry_options | Hash `or` block -> Hash | | |
|
271
|
+
| around_request | block | | |
|
272
|
+
| async_callback | block | | |
|
89
273
|
|
90
274
|
### Client
|
91
275
|
|
@@ -129,6 +313,42 @@ It holds the common configuration for all the endpoints (`Wrappi::Endpoint`).
|
|
129
313
|
"Auth-Token" => "verysecret"
|
130
314
|
}
|
131
315
|
```
|
316
|
+
- __async_handler:__ If you are not in Rails app or you have another background mechanism in place
|
317
|
+
you can configure here how the requests will be send to the background.
|
318
|
+
When `#async` is called on an Endpoint instance the `async_handler` const will be called with:
|
319
|
+
current endpoint instance (`self`) and the options passed to the async method.
|
320
|
+
```ruby
|
321
|
+
class MyAsyncHandler
|
322
|
+
def self.call(endpoint, opts)
|
323
|
+
# send to background
|
324
|
+
end
|
325
|
+
end
|
326
|
+
class Client < Wrappi::Client
|
327
|
+
setup do |config|
|
328
|
+
config.domain = 'https://api.github.com'
|
329
|
+
config.async_handler = MyAsyncHandler
|
330
|
+
end
|
331
|
+
end
|
332
|
+
endpoint_inst.async(this_opts_are_for_the_handler: true)
|
333
|
+
```
|
334
|
+
|
335
|
+
- __timeout:__ Set your specific timout. When you set timeout it will be merged with defaults.
|
336
|
+
|
337
|
+
default: `{ write: 9, connect: 9, read: 9 }`
|
338
|
+
|
339
|
+
```ruby
|
340
|
+
class Client < Wrappi::Client
|
341
|
+
setup do |config|
|
342
|
+
config.domain = 'https://api.github.com'
|
343
|
+
config.timeout = { read: 3 }
|
344
|
+
end
|
345
|
+
end
|
346
|
+
Client.timeout # => { write: 9, connect: 9, read: 3 }
|
347
|
+
```
|
348
|
+
|
349
|
+
- __use_ssl_context:__ It has to be set to `true` for using the `ssl_context`
|
350
|
+
|
351
|
+
default: `false`
|
132
352
|
|
133
353
|
- __ssl_context:__ If you need to set an ssl_context.
|
134
354
|
|
@@ -139,10 +359,6 @@ It holds the common configuration for all the endpoints (`Wrappi::Endpoint`).
|
|
139
359
|
end
|
140
360
|
```
|
141
361
|
|
142
|
-
- __use_ssl_context:__ It has to be set to `true` for using the `ssl_context`
|
143
|
-
|
144
|
-
default: `false`
|
145
|
-
|
146
362
|
### Endpoint
|
147
363
|
|
148
364
|
#### Required:
|
@@ -224,7 +440,7 @@ It holds the common configuration for all the endpoints (`Wrappi::Endpoint`).
|
|
224
440
|
end
|
225
441
|
```
|
226
442
|
|
227
|
-
- __follow_redirects:__ If
|
443
|
+
- __follow_redirects:__ If the request responds with a redirection it will follow them.
|
228
444
|
|
229
445
|
default: `true`
|
230
446
|
|
@@ -236,6 +452,21 @@ It holds the common configuration for all the endpoints (`Wrappi::Endpoint`).
|
|
236
452
|
- :form
|
237
453
|
- :body (Binary data)
|
238
454
|
|
455
|
+
- __async_callback:__ When request is executed in the background with `#async(opts = {})` this
|
456
|
+
callback will be called with this opts as and argument in the block.
|
457
|
+
The block is executed in the endpoint instance. You can access to all the methods in Endpoint.
|
458
|
+
|
459
|
+
default: `proc {}`
|
460
|
+
|
461
|
+
```ruby
|
462
|
+
async_callback do |opts|
|
463
|
+
if success?
|
464
|
+
MyCreationService.call(body) if opts[:create]
|
465
|
+
end
|
466
|
+
end
|
467
|
+
MyEndpoint.new().async(create: true)
|
468
|
+
```
|
469
|
+
|
239
470
|
#### Flow Control:
|
240
471
|
|
241
472
|
This configs allows you fine tune your request adding middleware, retries and cache.
|
@@ -249,7 +480,7 @@ It holds the common configuration for all the endpoints (`Wrappi::Endpoint`).
|
|
249
480
|
|
250
481
|
- __cache:__ Cache the request if successful.
|
251
482
|
|
252
|
-
default: `
|
483
|
+
default: `proc { options[:cache] }`
|
253
484
|
- __cache_options:__ Options for the `cache` to receive on `write`
|
254
485
|
```ruby
|
255
486
|
cache_options expires_in: 12, another_opt: true
|
@@ -300,11 +531,10 @@ It holds the common configuration for all the endpoints (`Wrappi::Endpoint`).
|
|
300
531
|
|
301
532
|
After checking out the repo, run `bin/setup` to install dependencies.
|
302
533
|
|
303
|
-
Run test:
|
304
534
|
```
|
305
535
|
bin/dev_server
|
306
536
|
```
|
307
|
-
This will run a rails server. The test are running
|
537
|
+
This will run a rails server. The test are running against it.
|
308
538
|
|
309
539
|
```
|
310
540
|
bundle exec rspec
|
data/lib/wrappi.rb
CHANGED
@@ -7,8 +7,11 @@ require 'retryable'
|
|
7
7
|
module Wrappi
|
8
8
|
class TimeoutError < StandardError; end
|
9
9
|
class NotAuthorizedAccessError < StandardError; end
|
10
|
+
class JsonParseError < StandardError; end
|
10
11
|
end
|
11
12
|
|
13
|
+
require 'wrappi/async_job'
|
14
|
+
require 'wrappi/async_handler'
|
12
15
|
require 'wrappi/client'
|
13
16
|
require 'wrappi/executer'
|
14
17
|
require 'wrappi/endpoint'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Wrappi
|
2
|
+
class AsyncHandler
|
3
|
+
def self.call(*args)
|
4
|
+
new(*args).call
|
5
|
+
end
|
6
|
+
attr_reader :endpoint, :options
|
7
|
+
def initialize(endpoint, options)
|
8
|
+
@endpoint = endpoint
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
AsyncJob.set((options[:set] || {}))
|
14
|
+
.perform_later(endpoint.class.to_s, { params: endpoint.input_params, options: endpoint.options }, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Wrappi
|
2
|
+
module AsyncConcern
|
3
|
+
def wrappi_perform(endpoint_class, args, options)
|
4
|
+
@endpoint_class = endpoint_class
|
5
|
+
@args = parse(args)
|
6
|
+
@options = parse(options)
|
7
|
+
return unless endpoint_const
|
8
|
+
inst = endpoint_const.new(@args[:params], @args[:options])
|
9
|
+
inst.perform_async_callback(@options)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse(data)
|
15
|
+
return ia(data) if data.is_a?(Hash)
|
16
|
+
ia(JSON.parse(data)) rescue {}
|
17
|
+
rescue
|
18
|
+
data
|
19
|
+
end
|
20
|
+
|
21
|
+
def ia(data)
|
22
|
+
Fusu::HashWithIndifferentAccess.new(data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def endpoint_const
|
26
|
+
Class.const_get(@endpoint_class)
|
27
|
+
rescue
|
28
|
+
puts "[Wrappi] Unable to find const #{@endpoint_class} for async"
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
if defined?(ActiveJob)
|
33
|
+
class Async < ActiveJob::Base
|
34
|
+
include AsyncConcern
|
35
|
+
def perform(*args)
|
36
|
+
wrappi_perform(*args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
class AsyncJob
|
41
|
+
include AsyncConcern
|
42
|
+
def self.set(options = {})
|
43
|
+
self
|
44
|
+
end
|
45
|
+
def self.perform_later(*args)
|
46
|
+
puts "Unable to perform async ActiveJob is not installed"
|
47
|
+
new().wrappi_perform(*args)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/wrappi/client.rb
CHANGED
@@ -2,10 +2,6 @@ require 'logger'
|
|
2
2
|
module Wrappi
|
3
3
|
# This class is expected to handle all the configurations for your main module
|
4
4
|
class Client
|
5
|
-
class TimeoutError < StandardError; end
|
6
|
-
class JsonParseError < StandardError; end
|
7
|
-
class NotAuthorizedAccessError < StandardError; end
|
8
|
-
|
9
5
|
include Fusu::Configurable
|
10
6
|
|
11
7
|
# Not verify example
|
@@ -21,6 +17,7 @@ module Wrappi
|
|
21
17
|
end
|
22
18
|
config_accessor(:params) { {} }
|
23
19
|
config_accessor(:cache)
|
20
|
+
config_accessor(:async_handler) { AsyncHandler }
|
24
21
|
|
25
22
|
def self.setup
|
26
23
|
yield(self)
|
data/lib/wrappi/endpoint.rb
CHANGED
@@ -4,6 +4,7 @@ module Wrappi
|
|
4
4
|
:verb, :client, :path, :default_params,
|
5
5
|
:headers, :follow_redirects, :basic_auth,
|
6
6
|
:body_type, :retry_options, :cache, :cache_options,
|
7
|
+
:async_callback,
|
7
8
|
default_config: {
|
8
9
|
verb: :get,
|
9
10
|
client: proc { raise 'client not set' }, # TODO: add proper error
|
@@ -12,8 +13,9 @@ module Wrappi
|
|
12
13
|
headers: proc { client.headers },
|
13
14
|
follow_redirects: true,
|
14
15
|
body_type: :json,
|
15
|
-
cache:
|
16
|
-
cache_options: {}
|
16
|
+
cache: proc { options[:cache] },
|
17
|
+
cache_options: {},
|
18
|
+
async_callback: proc {}
|
17
19
|
}
|
18
20
|
)
|
19
21
|
attr_reader :input_params, :options
|
@@ -26,18 +28,19 @@ module Wrappi
|
|
26
28
|
new(*args).call
|
27
29
|
end
|
28
30
|
|
29
|
-
def
|
30
|
-
|
31
|
+
def response
|
32
|
+
@response ||= Executer.call(self)
|
31
33
|
end
|
34
|
+
alias_method :call, :response
|
32
35
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
def body; response.body end
|
37
|
+
def success?; response.success? end
|
38
|
+
def status; response.status end
|
39
|
+
def error?; !success? end
|
40
|
+
def flush; @response = nil end
|
41
|
+
|
42
|
+
def async(async_options = {})
|
43
|
+
async_handler.call(self, async_options)
|
41
44
|
end
|
42
45
|
|
43
46
|
# overridable
|
@@ -45,42 +48,62 @@ module Wrappi
|
|
45
48
|
params
|
46
49
|
end
|
47
50
|
|
48
|
-
def
|
49
|
-
|
51
|
+
def url
|
52
|
+
_url.to_s
|
50
53
|
end
|
51
|
-
alias_method :call, :response
|
52
54
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
55
|
+
def url_with_params
|
56
|
+
return url unless verb == :get
|
57
|
+
_url.tap do |u|
|
58
|
+
u.query = URI.encode_www_form(consummated_params) if consummated_params.any?
|
59
|
+
end.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def self.async_callback(&block)
|
64
|
+
@async_callback = block
|
65
|
+
end
|
56
66
|
|
57
|
-
# AROUND REQUEST
|
58
67
|
def self.around_request(&block)
|
59
68
|
@around_request = block
|
60
69
|
end
|
61
|
-
def around_request
|
62
|
-
self.class.instance_variable_get(:@around_request)
|
63
|
-
end
|
64
70
|
|
65
|
-
# RETRY
|
66
71
|
def self.retry_if(&block)
|
67
72
|
@retry_if = block
|
68
73
|
end
|
69
|
-
|
70
|
-
|
74
|
+
|
75
|
+
def perform_async_callback(async_options = {})
|
76
|
+
instance_exec(async_options, &async_callback)
|
71
77
|
end
|
72
78
|
|
73
|
-
# Cache
|
74
79
|
def cache_key
|
75
80
|
# TODO: think headers have to be in the key as well
|
76
81
|
@cache_key ||= "[#{verb.to_s.upcase}]##{url}#{params_cache_key}"
|
77
82
|
end
|
78
83
|
|
84
|
+
def around_request
|
85
|
+
self.class.instance_variable_get(:@around_request)
|
86
|
+
end
|
87
|
+
|
88
|
+
def retry_if
|
89
|
+
self.class.instance_variable_get(:@retry_if)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def async_callback
|
95
|
+
self.class.instance_variable_get(:@async_callback) || proc {}
|
96
|
+
end
|
97
|
+
|
98
|
+
|
79
99
|
def logger
|
80
100
|
client.logger
|
81
101
|
end
|
82
102
|
|
83
|
-
|
103
|
+
# Overridable
|
104
|
+
def async_handler
|
105
|
+
client.async_handler
|
106
|
+
end
|
84
107
|
|
85
108
|
def params_cache_key
|
86
109
|
return if params.empty?
|
data/lib/wrappi/version.rb
CHANGED
data/wrappi.gemspec
CHANGED
@@ -9,8 +9,13 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Artur Pañach"]
|
10
10
|
spec.email = ["arturictus@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{Framework to create
|
12
|
+
spec.summary = %q{Making APIs fun again!}
|
13
|
+
spec.description = %q{Wrappi is a Framework to create API clients.
|
14
|
+
The intention is to bring the best practices and standardize how API clients behave.
|
15
|
+
It allows to create API clients in a declarative way improving readability and unifying the behavior.
|
16
|
+
It abstracts complex operations like caching, retries, background request and error handling.
|
17
|
+
|
18
|
+
Enjoy!}
|
14
19
|
spec.homepage = "https://github.com/arturictus/wrappi"
|
15
20
|
spec.license = "MIT"
|
16
21
|
|
@@ -19,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
19
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
25
|
spec.require_paths = ["lib"]
|
21
26
|
|
22
|
-
spec.add_development_dependency "bundler"
|
27
|
+
spec.add_development_dependency "bundler"
|
23
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
29
|
spec.add_development_dependency "rspec", "~> 3.0"
|
25
30
|
spec.add_development_dependency "sinatra"
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wrappi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artur Pañach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
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: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,8 +122,13 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
-
description:
|
126
|
-
|
125
|
+
description: |-
|
126
|
+
Wrappi is a Framework to create API clients.
|
127
|
+
The intention is to bring the best practices and standardize how API clients behave.
|
128
|
+
It allows to create API clients in a declarative way improving readability and unifying the behavior.
|
129
|
+
It abstracts complex operations like caching, retries, background request and error handling.
|
130
|
+
|
131
|
+
Enjoy!
|
127
132
|
email:
|
128
133
|
- arturictus@gmail.com
|
129
134
|
executables: []
|
@@ -142,6 +147,8 @@ files:
|
|
142
147
|
- bin/dev_server
|
143
148
|
- bin/setup
|
144
149
|
- lib/wrappi.rb
|
150
|
+
- lib/wrappi/async_handler.rb
|
151
|
+
- lib/wrappi/async_job.rb
|
145
152
|
- lib/wrappi/cached_response.rb
|
146
153
|
- lib/wrappi/client.rb
|
147
154
|
- lib/wrappi/endpoint.rb
|
@@ -180,5 +187,5 @@ rubyforge_project:
|
|
180
187
|
rubygems_version: 2.7.6
|
181
188
|
signing_key:
|
182
189
|
specification_version: 4
|
183
|
-
summary:
|
190
|
+
summary: Making APIs fun again!
|
184
191
|
test_files: []
|