frenetic 1.0.0.alpha.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +16 -0
- data/.gitignore +1 -1
- data/.irbrc +1 -1
- data/.rubocop.yml +45 -0
- data/.travis.yml +2 -2
- data/Appraisals +1 -1
- data/LICENSE +1 -1
- data/README.md +15 -15
- data/Rakefile +1 -1
- data/gemfiles/faraday_08.gemfile.lock +8 -8
- data/gemfiles/faraday_09.gemfile.lock +8 -8
- data/lib/frenetic.rb +13 -10
- data/lib/frenetic/briefly_memoizable.rb +9 -7
- data/lib/frenetic/concerns/collection_rest_methods.rb +4 -5
- data/lib/frenetic/concerns/hal_linked.rb +12 -9
- data/lib/frenetic/concerns/member_rest_methods.rb +7 -10
- data/lib/frenetic/concerns/structured.rb +2 -2
- data/lib/frenetic/connection.rb +25 -17
- data/lib/frenetic/errors.rb +67 -2
- data/lib/frenetic/hypermedia_link.rb +19 -26
- data/lib/frenetic/hypermedia_link_set.rb +11 -14
- data/lib/frenetic/middleware/hal_json.rb +3 -4
- data/lib/frenetic/resource.rb +31 -25
- data/lib/frenetic/resource_collection.rb +3 -3
- data/lib/frenetic/resource_mockery.rb +7 -5
- data/lib/frenetic/version.rb +2 -2
- data/spec/briefly_memoizable_spec.rb +1 -1
- data/spec/concerns/hal_linked_spec.rb +5 -5
- data/spec/concerns/member_rest_methods_spec.rb +1 -1
- data/spec/concerns/structured_spec.rb +6 -5
- data/spec/connection_spec.rb +16 -4
- data/spec/fixtures/test_api_requests.rb +32 -28
- data/spec/frenetic_spec.rb +3 -3
- data/spec/hypermedia_link_set_spec.rb +3 -3
- data/spec/hypermedia_link_spec.rb +1 -1
- data/spec/middleware/hal_json_spec.rb +3 -3
- data/spec/resource_collection_spec.rb +3 -4
- data/spec/resource_mockery_spec.rb +29 -6
- data/spec/resource_spec.rb +30 -13
- data/spec/spec_helper.rb +1 -1
- data/spec/support/i18n.rb +1 -0
- data/spec/support/rspec.rb +1 -1
- data/spec/support/timecop.rb +1 -1
- data/spec/support/webmock.rb +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c762ec3d9f1ece32685aa4e6e6acf19d02db55fe
|
4
|
+
data.tar.gz: 44c50996e3b1b7e8a8261d7d2919636383f0de70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17ca597ab9f13709f63067da856c157ae6505256ce9ec1f0feee51acb2be029c933da95fd6ce2868138f6fe0399824cf5755214845b914303685b2e2378ed539
|
7
|
+
data.tar.gz: 7d0571cd0e36780c57b4a9edd6e6d805fcfdbc0f0b58fddbc4b9258d642a2c5970d33ae7e3d9ff28f714c9c64fdb6abce317030a753f63a07505152df5687f58
|
data/.editorconfig
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# EditorConfig helps developers define and maintain consistent
|
2
|
+
# coding styles between different editors and IDEs
|
3
|
+
# editorconfig.org
|
4
|
+
|
5
|
+
root = true
|
6
|
+
|
7
|
+
[*]
|
8
|
+
# Change these settings to your own preference
|
9
|
+
indent_style = space
|
10
|
+
indent_size = 2
|
11
|
+
|
12
|
+
# We recommend you to keep these unchanged
|
13
|
+
end_of_line = lf
|
14
|
+
charset = utf-8
|
15
|
+
trim_trailing_whitespace = true
|
16
|
+
insert_final_newline = true
|
data/.gitignore
CHANGED
data/.irbrc
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- '*.gemspec'
|
4
|
+
|
5
|
+
Metrics/ClassLength:
|
6
|
+
Max: 120
|
7
|
+
|
8
|
+
Metrics/LineLength:
|
9
|
+
Max: 100
|
10
|
+
|
11
|
+
Metrics/MethodLength:
|
12
|
+
Max: 15
|
13
|
+
|
14
|
+
Style/AccessModifierIndentation:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Style/ClassVars:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Style/ConstantName:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Style/Documentation:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Style/NegatedIf:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Style/RaiseArgs:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
Style/SpaceAfterColon:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
Style/SpaceBeforeBlockBraces:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
Style/SpaceInsideBlockBraces:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Style/SpaceInsideParens:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Style/TrivialAccessors:
|
45
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
rvm:
|
2
|
-
- 1.
|
3
|
-
script: bundle exec rspec --require spec_helper --order rand --color --format documentation
|
2
|
+
- 2.1.2
|
3
|
+
script: bundle exec rspec --require spec_helper --order rand --color --format documentation
|
data/Appraisals
CHANGED
data/LICENSE
CHANGED
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -139,7 +139,7 @@ Initializing an API client is really easy:
|
|
139
139
|
class MyApiClient
|
140
140
|
# Arbitrary example
|
141
141
|
def self.api
|
142
|
-
@api ||= Frenetic.new(
|
142
|
+
@api ||= Frenetic.new(url:'http://example.com/api')
|
143
143
|
end
|
144
144
|
end
|
145
145
|
```
|
@@ -152,7 +152,7 @@ At the bare minimum, Frenetic only needs to know what the URL of your API is.
|
|
152
152
|
Configuring Frenetic can be done during instantiation:
|
153
153
|
|
154
154
|
```ruby
|
155
|
-
Frenetic.new(
|
155
|
+
Frenetic.new(url:'http://example.com', api_token:'123bada55k3y')
|
156
156
|
```
|
157
157
|
|
158
158
|
Or with a block:
|
@@ -168,7 +168,7 @@ end
|
|
168
168
|
Or both...
|
169
169
|
|
170
170
|
```ruby
|
171
|
-
f = Frenetic.new(
|
171
|
+
f = Frenetic.new(url:'http://example.com')
|
172
172
|
f.configure do |cfg|
|
173
173
|
cfg.api_token = '123bada55key'
|
174
174
|
end
|
@@ -184,13 +184,13 @@ middleware.
|
|
184
184
|
To use Basic Auth, simply configure Frenetic with a `username` and `password`:
|
185
185
|
|
186
186
|
```ruby
|
187
|
-
Frenetic.new(
|
187
|
+
Frenetic.new(url:url, username:'user', password:'password')
|
188
188
|
```
|
189
189
|
|
190
190
|
If your API uses an App ID and API Key pair, you can pass those as well:
|
191
191
|
|
192
192
|
```ruby
|
193
|
-
Frenetic.new(
|
193
|
+
Frenetic.new(url:url, app_id:'123abcSHA1', api_key:'bada55SHA1k3y')
|
194
194
|
```
|
195
195
|
|
196
196
|
The `app_id` and `api_key` values are simply aliases to `username` and
|
@@ -201,7 +201,7 @@ The `app_id` and `api_key` values are simply aliases to `username` and
|
|
201
201
|
To use Token Auth, simply configure Frenetic with your token:
|
202
202
|
|
203
203
|
```ruby
|
204
|
-
Frenetic.new(
|
204
|
+
Frenetic.new(url:url, api_token:'bada55SHA1t0k3n')
|
205
205
|
```
|
206
206
|
|
207
207
|
|
@@ -214,7 +214,7 @@ If configured to do so, Frenetic will autotmatically cache API responses.
|
|
214
214
|
##### Rack::Cache
|
215
215
|
|
216
216
|
```ruby
|
217
|
-
Frenetic.new(
|
217
|
+
Frenetic.new(url:url, cache: :rack)
|
218
218
|
```
|
219
219
|
|
220
220
|
Passing in a cache option of `:rack` will cause Frenetic to use Faraday's
|
@@ -246,14 +246,14 @@ By default, Frenetic is configured to use Faraday's default adapter (usually
|
|
246
246
|
Net::HTTP). You can change this with the `adapter` option:
|
247
247
|
|
248
248
|
```ruby
|
249
|
-
Frenetic.new(
|
249
|
+
Frenetic.new(url:url, adapter: :patron)
|
250
250
|
```
|
251
251
|
|
252
252
|
Frenetic accepts any of the [Faraday adapter shortcuts][adapters], or an instance
|
253
253
|
of the adapter itself:
|
254
254
|
|
255
255
|
```ruby
|
256
|
-
Frenetic.new(
|
256
|
+
Frenetic.new(url:url, adapter:Faraday::Adapter::Patron)
|
257
257
|
```
|
258
258
|
|
259
259
|
|
@@ -263,7 +263,7 @@ If you have no control over the API, you can explicitly tell Frenetic how long
|
|
263
263
|
to cache the API description for:
|
264
264
|
|
265
265
|
```ruby
|
266
|
-
Frenetic.new(
|
266
|
+
Frenetic.new(url:url, default_root_cache_age:1.hour)
|
267
267
|
```
|
268
268
|
|
269
269
|
|
@@ -273,7 +273,7 @@ Frenetic.new( url:url, default_root_cache_age:1.hour )
|
|
273
273
|
Frenetic will yield its internal Faraday connection during initialization:
|
274
274
|
|
275
275
|
```ruby
|
276
|
-
Frenetic.new(
|
276
|
+
Frenetic.new(url:url) do |builder|
|
277
277
|
# `builder` is the Faraday Connection instance with which you can
|
278
278
|
# add additional Faraday Middlewares or tweak the configuration.
|
279
279
|
end
|
@@ -293,7 +293,7 @@ A Frenetic instance supports any HTTP verb that [Faraday][faraday] has
|
|
293
293
|
impletented. This includes GET, POST, PUT, PATCH, and DELETE.
|
294
294
|
|
295
295
|
```ruby
|
296
|
-
api = Frenetic.new(
|
296
|
+
api = Frenetic.new(url:url)
|
297
297
|
|
298
298
|
api.get '/my_things/1'
|
299
299
|
# { 'id' => 1, 'name' => 'My Thing', '_links' => { 'self' { 'href' => '/api/my_things/1' } } }
|
@@ -314,8 +314,8 @@ class Order < Frenetic::Resource
|
|
314
314
|
api_client { MyAPI }
|
315
315
|
|
316
316
|
# TODO: Write a better example for this.
|
317
|
-
def self.find_all_by_name(
|
318
|
-
api.get(
|
317
|
+
def self.find_all_by_name(name)
|
318
|
+
api.get(search_url(name)) and response.success?
|
319
319
|
end
|
320
320
|
end
|
321
321
|
```
|
@@ -411,7 +411,7 @@ stub out all of the HTTP requests with something like WebMock or VCR, or you can
|
|
411
411
|
use Frenetic in `test_mode`
|
412
412
|
|
413
413
|
```ruby
|
414
|
-
Frenetic.new(
|
414
|
+
Frenetic.new(url:url, test_mode:true)
|
415
415
|
# ...or...
|
416
416
|
api = Frenetic.new(url:url)
|
417
417
|
api.config.test_mode = true
|
data/Rakefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
require
|
2
|
+
require 'bundler/gem_tasks'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../
|
3
3
|
specs:
|
4
|
-
frenetic (0.0
|
4
|
+
frenetic (1.0.0)
|
5
5
|
activesupport (>= 3)
|
6
6
|
addressable (~> 2.3.4)
|
7
7
|
faraday (>= 0.8)
|
@@ -10,11 +10,11 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
activesupport (4.1
|
14
|
-
i18n (~> 0.
|
13
|
+
activesupport (4.2.1)
|
14
|
+
i18n (~> 0.7)
|
15
15
|
json (~> 1.7, >= 1.7.7)
|
16
16
|
minitest (~> 5.1)
|
17
|
-
thread_safe (~> 0.
|
17
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
18
18
|
tzinfo (~> 1.1)
|
19
19
|
addressable (2.3.6)
|
20
20
|
appraisal (1.0.2)
|
@@ -31,9 +31,9 @@ GEM
|
|
31
31
|
faraday (~> 0.8)
|
32
32
|
faraday_middleware (0.8.8)
|
33
33
|
faraday (>= 0.7.4, < 0.9)
|
34
|
-
i18n (0.
|
35
|
-
json (1.8.
|
36
|
-
minitest (5.
|
34
|
+
i18n (0.7.0)
|
35
|
+
json (1.8.2)
|
36
|
+
minitest (5.5.1)
|
37
37
|
multipart-post (1.2.0)
|
38
38
|
rack (1.5.2)
|
39
39
|
rack-cache (1.2)
|
@@ -53,7 +53,7 @@ GEM
|
|
53
53
|
rspec-support (3.0.4)
|
54
54
|
safe_yaml (1.0.3)
|
55
55
|
thor (0.19.1)
|
56
|
-
thread_safe (0.3.
|
56
|
+
thread_safe (0.3.5)
|
57
57
|
timecop (0.7.1)
|
58
58
|
tzinfo (1.2.2)
|
59
59
|
thread_safe (~> 0.1)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../
|
3
3
|
specs:
|
4
|
-
frenetic (0.0
|
4
|
+
frenetic (1.0.0)
|
5
5
|
activesupport (>= 3)
|
6
6
|
addressable (~> 2.3.4)
|
7
7
|
faraday (>= 0.8)
|
@@ -10,11 +10,11 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
activesupport (4.1
|
14
|
-
i18n (~> 0.
|
13
|
+
activesupport (4.2.1)
|
14
|
+
i18n (~> 0.7)
|
15
15
|
json (~> 1.7, >= 1.7.7)
|
16
16
|
minitest (~> 5.1)
|
17
|
-
thread_safe (~> 0.
|
17
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
18
18
|
tzinfo (~> 1.1)
|
19
19
|
addressable (2.3.6)
|
20
20
|
appraisal (1.0.2)
|
@@ -31,9 +31,9 @@ GEM
|
|
31
31
|
faraday (~> 0.8)
|
32
32
|
faraday_middleware (0.9.1)
|
33
33
|
faraday (>= 0.7.4, < 0.10)
|
34
|
-
i18n (0.
|
35
|
-
json (1.8.
|
36
|
-
minitest (5.
|
34
|
+
i18n (0.7.0)
|
35
|
+
json (1.8.2)
|
36
|
+
minitest (5.5.1)
|
37
37
|
multipart-post (2.0.0)
|
38
38
|
rack (1.5.2)
|
39
39
|
rack-cache (1.2)
|
@@ -53,7 +53,7 @@ GEM
|
|
53
53
|
rspec-support (3.0.4)
|
54
54
|
safe_yaml (1.0.3)
|
55
55
|
thor (0.19.1)
|
56
|
-
thread_safe (0.3.
|
56
|
+
thread_safe (0.3.5)
|
57
57
|
timecop (0.7.1)
|
58
58
|
tzinfo (1.2.2)
|
59
59
|
thread_safe (~> 0.1)
|
data/lib/frenetic.rb
CHANGED
@@ -17,6 +17,8 @@ class Frenetic
|
|
17
17
|
include ActiveSupport::Configurable
|
18
18
|
include BrieflyMemoizable
|
19
19
|
|
20
|
+
MaxAge = /max-age=(?<max_age>\d+)/
|
21
|
+
|
20
22
|
config_accessor :adapter
|
21
23
|
config_accessor :api_token
|
22
24
|
config_accessor :cache
|
@@ -49,12 +51,12 @@ class Frenetic
|
|
49
51
|
url: nil,
|
50
52
|
username: nil
|
51
53
|
}
|
52
|
-
|
54
|
+
config.merge!(@@defaults)
|
53
55
|
|
54
56
|
# PENDING: [ActiveSupport4] Remove merge with class defaults
|
55
57
|
def initialize(cfg = {})
|
56
|
-
|
57
|
-
yield
|
58
|
+
config.merge!(cfg.reverse_merge(self.class.config))
|
59
|
+
yield config if block_given?
|
58
60
|
end
|
59
61
|
|
60
62
|
def connection
|
@@ -74,10 +76,10 @@ class Frenetic
|
|
74
76
|
#
|
75
77
|
# If no Cache-Control header is returned, then the results are not memoized.
|
76
78
|
def description
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
79
|
+
response = get(config.url.to_s)
|
80
|
+
return unless response.success?
|
81
|
+
@description_age = cache_control_age(response.headers)
|
82
|
+
response.body
|
81
83
|
end
|
82
84
|
briefly_memoize :description
|
83
85
|
|
@@ -92,11 +94,12 @@ class Frenetic
|
|
92
94
|
private
|
93
95
|
|
94
96
|
def cache_control_age(headers)
|
95
|
-
|
96
|
-
|
97
|
+
cache_age = headers['Cache-Control']
|
98
|
+
if cache_age
|
99
|
+
age = cache_age.match(MaxAge)[:max_age]
|
97
100
|
Time.now + age.to_i
|
98
101
|
else
|
99
102
|
config.default_root_cache_age
|
100
103
|
end
|
101
104
|
end
|
102
|
-
end
|
105
|
+
end
|
@@ -8,14 +8,15 @@ class Frenetic
|
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
module ClassMethods
|
11
|
-
def briefly_memoize(
|
11
|
+
def briefly_memoize(symbol)
|
12
12
|
original_method = "_unmemoized_#{symbol}".to_sym
|
13
|
-
memoized_ivar
|
14
|
-
age_ivar
|
13
|
+
memoized_ivar = "@#{symbol}"
|
14
|
+
age_ivar = "@#{symbol}_age"
|
15
15
|
|
16
|
-
|
16
|
+
# rubocop:disable Metrics/LineLength
|
17
|
+
class_eval <<-CODE
|
17
18
|
if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type)
|
18
|
-
|
19
|
+
fail "Already memoized #{symbol}" # fail "Already memoized mime_type"
|
19
20
|
end # end
|
20
21
|
alias #{original_method} #{symbol} # alias _unmemoized_mime_type mime_type
|
21
22
|
|
@@ -27,8 +28,9 @@ class Frenetic
|
|
27
28
|
def reload_#{symbol}! # def reload_mime_type!
|
28
29
|
#{memoized_ivar} = nil # @mime_type = nil
|
29
30
|
end # end
|
30
|
-
|
31
|
+
CODE
|
32
|
+
# rubocop:enable Metrics/LineLength
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
34
|
-
end
|
36
|
+
end
|
@@ -4,10 +4,9 @@ class Frenetic
|
|
4
4
|
module CollectionRestMethods
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
def get(
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
def get(id)
|
8
|
+
response = api.get(member_url(id))
|
9
|
+
@resource_class.new(response.body) if response.success?
|
11
10
|
end
|
12
11
|
end
|
13
|
-
end
|
12
|
+
end
|
@@ -10,10 +10,11 @@ class Frenetic
|
|
10
10
|
@params['_links']
|
11
11
|
end
|
12
12
|
|
13
|
-
def member_url(
|
13
|
+
def member_url(params = {})
|
14
14
|
resource = @resource_type || self.class.to_s.demodulize.underscore
|
15
|
-
link = links[resource] || links['self']
|
16
|
-
|
15
|
+
link = links[resource] || links['self']
|
16
|
+
fail MissingResourceUrl.new(resource) if !link
|
17
|
+
HypermediaLinkSet.new(link).href params
|
17
18
|
end
|
18
19
|
|
19
20
|
module ClassMethods
|
@@ -21,15 +22,17 @@ class Frenetic
|
|
21
22
|
api.description['_links']
|
22
23
|
end
|
23
24
|
|
24
|
-
def member_url(
|
25
|
-
link = links[namespace]
|
26
|
-
|
25
|
+
def member_url(params = {})
|
26
|
+
link = links[namespace]
|
27
|
+
fail MissingResourceUrl.new(namespace) if !link
|
28
|
+
HypermediaLinkSet.new(link).href params
|
27
29
|
end
|
28
30
|
|
29
31
|
def collection_url
|
30
|
-
link = links[namespace.pluralize]
|
31
|
-
|
32
|
+
link = links[namespace.pluralize]
|
33
|
+
fail MissingResourceUrl.new(namespace.pluralize) if !link
|
34
|
+
HypermediaLinkSet.new(link).href
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
35
|
-
end
|
38
|
+
end
|