frenetic 1.0.0.alpha.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +16 -0
  3. data/.gitignore +1 -1
  4. data/.irbrc +1 -1
  5. data/.rubocop.yml +45 -0
  6. data/.travis.yml +2 -2
  7. data/Appraisals +1 -1
  8. data/LICENSE +1 -1
  9. data/README.md +15 -15
  10. data/Rakefile +1 -1
  11. data/gemfiles/faraday_08.gemfile.lock +8 -8
  12. data/gemfiles/faraday_09.gemfile.lock +8 -8
  13. data/lib/frenetic.rb +13 -10
  14. data/lib/frenetic/briefly_memoizable.rb +9 -7
  15. data/lib/frenetic/concerns/collection_rest_methods.rb +4 -5
  16. data/lib/frenetic/concerns/hal_linked.rb +12 -9
  17. data/lib/frenetic/concerns/member_rest_methods.rb +7 -10
  18. data/lib/frenetic/concerns/structured.rb +2 -2
  19. data/lib/frenetic/connection.rb +25 -17
  20. data/lib/frenetic/errors.rb +67 -2
  21. data/lib/frenetic/hypermedia_link.rb +19 -26
  22. data/lib/frenetic/hypermedia_link_set.rb +11 -14
  23. data/lib/frenetic/middleware/hal_json.rb +3 -4
  24. data/lib/frenetic/resource.rb +31 -25
  25. data/lib/frenetic/resource_collection.rb +3 -3
  26. data/lib/frenetic/resource_mockery.rb +7 -5
  27. data/lib/frenetic/version.rb +2 -2
  28. data/spec/briefly_memoizable_spec.rb +1 -1
  29. data/spec/concerns/hal_linked_spec.rb +5 -5
  30. data/spec/concerns/member_rest_methods_spec.rb +1 -1
  31. data/spec/concerns/structured_spec.rb +6 -5
  32. data/spec/connection_spec.rb +16 -4
  33. data/spec/fixtures/test_api_requests.rb +32 -28
  34. data/spec/frenetic_spec.rb +3 -3
  35. data/spec/hypermedia_link_set_spec.rb +3 -3
  36. data/spec/hypermedia_link_spec.rb +1 -1
  37. data/spec/middleware/hal_json_spec.rb +3 -3
  38. data/spec/resource_collection_spec.rb +3 -4
  39. data/spec/resource_mockery_spec.rb +29 -6
  40. data/spec/resource_spec.rb +30 -13
  41. data/spec/spec_helper.rb +1 -1
  42. data/spec/support/i18n.rb +1 -0
  43. data/spec/support/rspec.rb +1 -1
  44. data/spec/support/timecop.rb +1 -1
  45. data/spec/support/webmock.rb +1 -1
  46. metadata +8 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc9d5efbe7083a07d49bc6d57da6a9ad2125e37d
4
- data.tar.gz: 1d08f15fa29717b07f6bf43d6e46e8acc0832244
3
+ metadata.gz: c762ec3d9f1ece32685aa4e6e6acf19d02db55fe
4
+ data.tar.gz: 44c50996e3b1b7e8a8261d7d2919636383f0de70
5
5
  SHA512:
6
- metadata.gz: ce6cdbdf561f06c6b4b9120b0222e69f031ea316f634e97f70df742a9c4015344ad551b6b60d072e149014ddd537def35ab6bbe7fbbd11367116fe7482527522
7
- data.tar.gz: d70ca28073717ee35679abca5ef8107372ee7f3acf138070cdc40f91ef6a2b00481ddf49c5c76b9c6e6fcc86104e258c2f5407588d7b6c4b78abc1cb7e25a0de
6
+ metadata.gz: 17ca597ab9f13709f63067da856c157ae6505256ce9ec1f0feee51acb2be029c933da95fd6ce2868138f6fe0399824cf5755214845b914303685b2e2378ed539
7
+ data.tar.gz: 7d0571cd0e36780c57b4a9edd6e6d805fcfdbc0f0b58fddbc4b9258d642a2c5970d33ae7e3d9ff28f714c9c64fdb6abce317030a753f63a07505152df5687f58
@@ -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
@@ -16,4 +16,4 @@ spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
- vendor
19
+ vendor
data/.irbrc CHANGED
@@ -1,3 +1,3 @@
1
1
  require 'bundler'
2
2
  Bundler.require
3
- require 'awesome_print'
3
+ require 'awesome_print'
@@ -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
@@ -1,3 +1,3 @@
1
1
  rvm:
2
- - 1.9.3
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
@@ -6,4 +6,4 @@ end
6
6
  appraise 'faraday-09' do
7
7
  gem 'faraday', '~> 0.9.0'
8
8
  gem 'faraday_middleware', '~> 0.9.0'
9
- end
9
+ end
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( url:'http://example.com/api' )
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( url:'http://example.com', api_token:'123bada55k3y' )
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( url:'http://example.com' )
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( url:url, username:'user', password:'password' )
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( url:url, app_id:'123abcSHA1', api_key:'bada55SHA1k3y' )
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( url:url, api_token:'bada55SHA1t0k3n' )
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( url:url, cache: :rack )
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( url:url, adapter: :patron )
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( url:url, adapter:Faraday::Adapter::Patron )
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( url:url, default_root_cache_age:1.hour )
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( url:url ) do |builder|
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( url:url )
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( name )
318
- api.get( search_url(name) ) and response.success?
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( url:url, test_mode:true )
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 "bundler/gem_tasks"
2
+ require 'bundler/gem_tasks'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- frenetic (0.0.20.alpha.6)
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.5)
14
- i18n (~> 0.6, >= 0.6.9)
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.1)
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.6.11)
35
- json (1.8.1)
36
- minitest (5.4.1)
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.4)
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.20.alpha.6)
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.5)
14
- i18n (~> 0.6, >= 0.6.9)
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.1)
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.6.11)
35
- json (1.8.1)
36
- minitest (5.4.1)
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.4)
56
+ thread_safe (0.3.5)
57
57
  timecop (0.7.1)
58
58
  tzinfo (1.2.2)
59
59
  thread_safe (~> 0.1)
@@ -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
- self.config.merge!(@@defaults)
54
+ config.merge!(@@defaults)
53
55
 
54
56
  # PENDING: [ActiveSupport4] Remove merge with class defaults
55
57
  def initialize(cfg = {})
56
- self.config.merge!(cfg.reverse_merge(self.class.config))
57
- yield self.config if block_given?
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
- if response = get(config.url.to_s) and response.success?
78
- @description_age = cache_control_age(response.headers)
79
- response.body
80
- end
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
- if cache_age = headers['Cache-Control']
96
- age = cache_age.match(%r{max-age=(?<max_age>\d+)})[:max_age]
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( symbol )
11
+ def briefly_memoize(symbol)
12
12
  original_method = "_unmemoized_#{symbol}".to_sym
13
- memoized_ivar = "@#{symbol}"
14
- age_ivar = "@#{symbol}_age"
13
+ memoized_ivar = "@#{symbol}"
14
+ age_ivar = "@#{symbol}_age"
15
15
 
16
- class_eval <<-EOS
16
+ # rubocop:disable Metrics/LineLength
17
+ class_eval <<-CODE
17
18
  if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type)
18
- raise "Already memoized #{symbol}" # raise "Already memoized mime_type"
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
- EOS
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( id )
8
- if response = api.get( member_url(id) ) and response.success?
9
- @resource_class.new response.body
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( params = {} )
13
+ def member_url(params = {})
14
14
  resource = @resource_type || self.class.to_s.demodulize.underscore
15
- link = links[resource] || links['self'] or raise HypermediaError, %Q{No Hypermedia GET Url found for the resource "#{resource}"}
16
- HypermediaLinkSet.new( link ).href params
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( params = {} )
25
- link = links[namespace] or raise HypermediaError, %Q{No Hypermedia GET Url found for the resource "#{namespace}"}
26
- HypermediaLinkSet.new( link ).href params
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] or raise HypermediaError, %Q{No Hypermedia GET Url found for the resource "#{namespace.pluralize}"}
31
- HypermediaLinkSet.new( link ).href
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