frenetic 0.0.20.alpha.6 → 1.0.0.alpha.1

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -1
  3. data/Appraisals +9 -0
  4. data/Gemfile +1 -1
  5. data/README.md +2 -2
  6. data/frenetic.gemspec +8 -5
  7. data/gemfiles/faraday_08.gemfile +10 -0
  8. data/gemfiles/faraday_08.gemfile.lock +77 -0
  9. data/gemfiles/faraday_09.gemfile +10 -0
  10. data/gemfiles/faraday_09.gemfile.lock +77 -0
  11. data/lib/frenetic.rb +57 -30
  12. data/lib/frenetic/briefly_memoizable.rb +34 -0
  13. data/lib/frenetic/concerns/collection_rest_methods.rb +1 -1
  14. data/lib/frenetic/concerns/hal_linked.rb +5 -35
  15. data/lib/frenetic/concerns/member_rest_methods.rb +0 -2
  16. data/lib/frenetic/concerns/structured.rb +0 -5
  17. data/lib/frenetic/connection.rb +110 -0
  18. data/lib/frenetic/errors.rb +112 -0
  19. data/lib/frenetic/hypermedia_link.rb +74 -0
  20. data/lib/frenetic/hypermedia_link_set.rb +43 -0
  21. data/lib/frenetic/middleware/hal_json.rb +9 -12
  22. data/lib/frenetic/resource.rb +22 -6
  23. data/lib/frenetic/resource_collection.rb +0 -1
  24. data/lib/frenetic/resource_mockery.rb +55 -1
  25. data/lib/frenetic/version.rb +1 -1
  26. data/spec/{concerns/breifly_memoizable_spec.rb → briefly_memoizable_spec.rb} +10 -18
  27. data/spec/concerns/hal_linked_spec.rb +49 -62
  28. data/spec/concerns/member_rest_methods_spec.rb +8 -10
  29. data/spec/concerns/structured_spec.rb +70 -75
  30. data/spec/connection_spec.rb +137 -0
  31. data/spec/fixtures/test_api_requests.rb +8 -2
  32. data/spec/frenetic_spec.rb +221 -133
  33. data/spec/hypermedia_link_set_spec.rb +155 -0
  34. data/spec/hypermedia_link_spec.rb +153 -0
  35. data/spec/middleware/hal_json_spec.rb +13 -15
  36. data/spec/resource_collection_spec.rb +17 -16
  37. data/spec/resource_mockery_spec.rb +69 -0
  38. data/spec/resource_spec.rb +110 -63
  39. data/spec/support/rspec.rb +0 -1
  40. metadata +88 -75
  41. data/lib/frenetic/concerns/briefly_memoizable.rb +0 -34
  42. data/lib/frenetic/concerns/configurable.rb +0 -59
  43. data/lib/frenetic/concerns/resource_mockery.rb +0 -48
  44. data/lib/frenetic/configuration.rb +0 -88
  45. data/spec/concerns/configurable_spec.rb +0 -50
  46. data/spec/concerns/resource_mockery_spec.rb +0 -56
  47. data/spec/configuration_spec.rb +0 -134
@@ -1,34 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- # Memoizes method calls, but only for a specific period of time.
4
- # Useful for supporting HTTP Cache-Control without an external caching layer
5
- # like Rack::Cache
6
- module BrieflyMemoizable
7
- extend ActiveSupport::Concern
8
-
9
- module ClassMethods
10
- def briefly_memoize( symbol )
11
- original_method = "_unmemoized_#{symbol}".to_sym
12
- memoized_ivar = "@#{symbol}"
13
- age_ivar = "@#{symbol}_age"
14
-
15
- class_eval <<-EOS
16
- if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type)
17
- raise "Already memoized #{symbol}" # raise "Already memoized mime_type"
18
- end # end
19
- alias #{original_method} #{symbol} # alias _unmemoized_mime_type mime_type
20
-
21
- def #{symbol}(*args) # def mime_type(*args)
22
- #{memoized_ivar} = nil if #{age_ivar} && Time.now > #{age_ivar} # @mime_type = nil if @mime_type_age && Time.now > @mime_type_age
23
- #
24
- #{memoized_ivar} ||= #{original_method}(*args) # @mime_type ||= _unmemoized_mime_type(*args)
25
- end # end
26
-
27
- def reload_#{symbol}! # def reload_mime_type!
28
- #{memoized_ivar} = nil # @mime_type = nil
29
- end # end
30
- EOS
31
- end
32
- end
33
-
34
- end
@@ -1,59 +0,0 @@
1
- require 'active_support/configurable'
2
- require 'active_support/concern'
3
-
4
- require 'frenetic/configuration'
5
-
6
- class Frenetic
7
- module Configurable
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- include ActiveSupport::Configurable
12
- # Don't allow the class to be configured
13
- class << self
14
- undef :configure
15
- end
16
- end
17
-
18
- def initialize( cfg = {} )
19
- config.merge! Frenetic::Configuration.new(cfg).attributes
20
-
21
- @builder_config = Proc.new if block_given?
22
- end
23
-
24
- def configure
25
- yield config
26
- end
27
-
28
- private
29
-
30
- def validate_configuration!
31
- raise( ConfigError, 'A URL must be defined' ) unless config.url
32
- end
33
-
34
- def configure_authentication( builder )
35
- if config.username
36
- builder.request :basic_auth, config.username, config.password
37
- end
38
-
39
- if config.api_token
40
- builder.request :token_auth, config.api_token
41
- end
42
- end
43
-
44
- def configure_caching( builder )
45
- if config.cache[:metastore]
46
- dependency 'rack-cache'
47
-
48
- builder.use FaradayMiddleware::RackCompatible, Rack::Cache::Context, config.cache
49
- end
50
- end
51
-
52
- def dependency( lib = nil )
53
- lib ? require(lib) : yield
54
- rescue NameError, LoadError => err
55
- raise ConfigError, "Missing dependency for #{self}: #{err.message}"
56
- end
57
-
58
- end
59
- end
@@ -1,48 +0,0 @@
1
- require 'ostruct'
2
- require 'active_support/concern'
3
-
4
- class Frenetic
5
- module ResourceMockery
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- # I'm sure this violates some sort of CS principle or best practice,
10
- # but it solves the problem for now.
11
- superclass.send :instance_variable_set, '@mock_class', self
12
- end
13
-
14
- def attributes
15
- @params
16
- end
17
-
18
- def properties
19
- @params.each_with_object({}) do |(k,v), props|
20
- props[k] = v.class.to_s.underscore
21
- end
22
- end
23
-
24
- # Provides a place for a Resources that are mocked to declare reasonable
25
- # default values for Mock Resources
26
- def default_attributes
27
- {}
28
- end
29
-
30
- module ClassMethods
31
- def api_client
32
- superclass.api_client
33
- end
34
- end
35
-
36
- private
37
-
38
- def build_params( p )
39
- defaults = default_attributes.with_indifferent_access
40
- @params = defaults.merge( (p || {}).with_indifferent_access )
41
- end
42
-
43
- def build_structure
44
- @structure = OpenStruct.new( @attrs )
45
- end
46
-
47
- end
48
- end
@@ -1,88 +0,0 @@
1
- require 'addressable/uri'
2
- require 'active_support/core_ext/hash/indifferent_access'
3
-
4
- class Frenetic
5
- class Configuration
6
-
7
- @@defaults = {
8
- headers: {
9
- accept: 'application/hal+json',
10
- user_agent: "Frenetic v#{Frenetic::VERSION}; #{Socket.gethostname}"
11
- }
12
- }
13
-
14
- def initialize( cfg = {} )
15
- @_cfg = cfg.symbolize_keys
16
- end
17
-
18
- def adapter
19
- @_cfg[:adapter] || Faraday.default_adapter
20
- end
21
-
22
- def api_token
23
- @_cfg[:api_token]
24
- end
25
-
26
- def attributes
27
- {
28
- adapter: adapter,
29
- api_token: api_token,
30
- cache: cache,
31
- default_root_cache_age: default_root_cache_age,
32
- headers: headers,
33
- password: password,
34
- ssl: ssl,
35
- test_mode: test_mode,
36
- url: url,
37
- username: username
38
- }
39
- end
40
-
41
- def cache
42
- if @_cfg[:cache] == :rack
43
- {
44
- metastore: 'file:tmp/rack/meta',
45
- entitystore: 'file:tmp/rack/body',
46
- ignore_headers: %w{Authorization Set-Cookie X-Content-Digest}
47
- }
48
- else
49
- {}
50
- end
51
- end
52
-
53
- def default_root_cache_age
54
- @_cfg[:default_root_cache_age]
55
- end
56
-
57
- def headers
58
- @@defaults[:headers].merge( @_cfg[:headers] || {} ).tap do |h|
59
- if @_cfg[:headers] && @_cfg[:headers][:user_agent]
60
- if h[:user_agent] != @@defaults[:headers][:user_agent]
61
- h[:user_agent] = "#{h[:user_agent]} (#{@@defaults[:headers][:user_agent]})"
62
- end
63
- end
64
- end
65
- end
66
-
67
- def password
68
- @_cfg[:password] || @_cfg[:api_key]
69
- end
70
-
71
- def ssl
72
- @_cfg[:ssl] || { verify:true }
73
- end
74
-
75
- def test_mode
76
- @_cfg[:test_mode] || false
77
- end
78
-
79
- def url
80
- Addressable::URI.parse @_cfg[:url]
81
- end
82
-
83
- def username
84
- @_cfg[:username] || @_cfg[:app_id]
85
- end
86
-
87
- end
88
- end
@@ -1,50 +0,0 @@
1
- describe Frenetic::Configurable do
2
- let(:test_cfg) do
3
- {
4
- url:'http://example.org'
5
- }
6
- end
7
-
8
- subject(:instance) { Frenetic.new( test_cfg ) }
9
-
10
- describe '#config' do
11
- subject { instance.config }
12
-
13
- it { should_not be_empty }
14
- end
15
-
16
- describe '#configure' do
17
- subject do
18
- cfg = nil
19
- instance.configure { |c| cfg = c }
20
- cfg
21
- end
22
-
23
- it 'should yield the configuration' do
24
- subject.should be_a Hash
25
- end
26
- end
27
-
28
- describe '.configure' do
29
- subject { Frenetic.configure{|c|} }
30
-
31
- it 'should not exist' do
32
- expect{ subject }.to raise_error NoMethodError
33
- end
34
- end
35
-
36
- describe '#initialize' do
37
- let(:callback) do
38
- Proc.new { |b| }
39
- end
40
-
41
- subject do
42
- Frenetic.new( &callback ).instance_variable_get( "@builder_config" )
43
- end
44
-
45
- it 'retain block arguments' do
46
- subject.should eq callback
47
- end
48
- end
49
-
50
- end
@@ -1,56 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'frenetic/resource_mockery'
4
-
5
- describe Frenetic::ResourceMockery do
6
- let(:my_temp_resource) do
7
- Class.new(Frenetic::Resource)
8
- end
9
-
10
- let(:my_mocked_resource) do
11
- Class.new(my_temp_resource) do
12
- def default_attributes
13
- { qux:'qux' }
14
- end
15
- end
16
- end
17
-
18
- before do
19
- stub_const 'MyNamespace::MyMockedResource', my_mocked_resource
20
-
21
- MyNamespace::MyMockedResource.send :include, described_class
22
- end
23
-
24
- let(:params) { { foo:1, bar:'baz' } }
25
-
26
- subject { MyNamespace::MyMockedResource.new params }
27
-
28
- it 'should violate some basic CS principles by telling the parent-class of its existence' do
29
- expect(my_temp_resource.instance_variables).to include :@mock_class
30
- end
31
-
32
- describe '#properties' do
33
- subject { super().properties }
34
-
35
- it 'should return a hash of available properties' do
36
- subject.should include 'foo' => 'fixnum'
37
- subject.should include 'bar' => 'string'
38
- end
39
- end
40
-
41
- describe '#attributes' do
42
- subject { super().attributes }
43
-
44
- it 'should return a hash of the resources attributes' do
45
- subject.should include 'foo' => 1
46
- subject.should include 'bar' => 'baz'
47
- subject.should include 'qux' => 'qux'
48
- end
49
- end
50
-
51
- describe '#default_attributes' do
52
- it 'should allow implementors to specify sane defaults' do
53
- subject.qux.should == 'qux'
54
- end
55
- end
56
- end
@@ -1,134 +0,0 @@
1
- describe Frenetic::Configuration do
2
- let(:cfg) { Hash.new }
3
-
4
- subject(:instance) { described_class.new cfg }
5
-
6
- describe '#adapter' do
7
- subject { instance.adapter }
8
-
9
- it { should == :net_http }
10
- end
11
-
12
- describe '#attributes' do
13
- subject { instance.attributes }
14
-
15
- it { should include :adapter }
16
- it { should include :api_token }
17
- it { should include :cache }
18
- it { should include :default_root_cache_age }
19
- it { should include :headers }
20
- it { should include :password }
21
- it { should include :ssl }
22
- it { should include :test_mode }
23
- it { should include :url }
24
- it { should include :username }
25
- end
26
-
27
- describe '#api_token' do
28
- let(:cfg) do
29
- { api_token:'API_TOKEN' }
30
- end
31
-
32
- subject { instance.api_token }
33
-
34
- it { should == 'API_TOKEN' }
35
- end
36
-
37
- describe '#cache' do
38
- subject { instance.cache }
39
-
40
- context 'with a value of :rack' do
41
- let(:cfg) do
42
- { cache: :rack }
43
- end
44
-
45
- it 'should return Rack::Cache options' do
46
- subject.should include metastore:'file:tmp/rack/meta'
47
- subject.should include entitystore:'file:tmp/rack/body'
48
- subject.should include ignore_headers:%w{Authorization Set-Cookie X-Content-Digest}
49
- end
50
- end
51
- end
52
-
53
- describe '#default_root_cache_age' do
54
- let(:cfg) do
55
- { default_root_cache_age:3600 }
56
- end
57
-
58
- subject { instance.default_root_cache_age }
59
-
60
- it { should == 3600 }
61
- end
62
-
63
- describe '#headers' do
64
- let(:cfg) do
65
- { headers:{ accept:'MIME', x_foo:'BAR' } }
66
- end
67
-
68
- subject { instance.headers }
69
-
70
- it 'should properly merge in nested header values' do
71
- subject.should include :user_agent
72
- subject.should include accept:'MIME'
73
- subject.should include x_foo:'BAR'
74
- end
75
-
76
- context 'with a custom User-Agent' do
77
- let(:cfg) do
78
- { headers:{ user_agent:'Foo v1.1' } }
79
- end
80
-
81
- it 'should append the Frenentic User-Agent' do
82
- subject[:user_agent].should match %r{\AFoo v1.1 \(Frenetic v.[^;]*; [^)]*\)\Z}
83
- end
84
- end
85
- end
86
-
87
- describe '#password' do
88
- subject { instance.password }
89
-
90
- context 'with a specifed Api key' do
91
- let(:cfg) do
92
- { api_key:'API_KEY' }
93
- end
94
-
95
- it { should == 'API_KEY' }
96
- end
97
- end
98
-
99
- describe '#ssl' do
100
- subject { instance.ssl }
101
-
102
- it { should include verify:true }
103
- end
104
-
105
- describe '#test_mode' do
106
- subject { instance.test_mode }
107
-
108
- it { should be_false }
109
- end
110
-
111
- describe '#url' do
112
- let(:cfg) do
113
- { url:'http://example.org' }
114
- end
115
-
116
- subject { instance.url }
117
-
118
- it { should be_a Addressable::URI }
119
-
120
- its(:to_s) { should == 'http://example.org' }
121
- end
122
-
123
- describe '#username' do
124
- subject { instance.username }
125
-
126
- context 'with a specifed App Id' do
127
- let(:cfg) do
128
- { app_id:'APP_ID' }
129
- end
130
-
131
- it { should == 'APP_ID' }
132
- end
133
- end
134
- end