acfs 0.2.0 → 0.3.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.
Files changed (45) hide show
  1. data/.gitignore +0 -1
  2. data/.travis.yml +1 -3
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +45 -7
  5. data/acfs.gemspec +3 -0
  6. data/gemfiles/{Gemfile.rails-3-1 → Gemfile.rails-4-0} +2 -2
  7. data/lib/acfs.rb +49 -5
  8. data/lib/acfs/adapter/typhoeus.rb +42 -0
  9. data/lib/acfs/collection.rb +22 -0
  10. data/lib/acfs/middleware/base.rb +21 -0
  11. data/lib/acfs/middleware/json_decoder.rb +15 -0
  12. data/lib/acfs/middleware/print.rb +23 -0
  13. data/lib/acfs/model.rb +25 -12
  14. data/lib/acfs/{attributes.rb → model/attributes.rb} +36 -40
  15. data/lib/acfs/model/attributes/integer.rb +18 -0
  16. data/lib/acfs/model/attributes/string.rb +18 -0
  17. data/lib/acfs/{initialization.rb → model/initialization.rb} +4 -1
  18. data/lib/acfs/model/loadable.rb +18 -0
  19. data/lib/acfs/model/locatable.rb +24 -0
  20. data/lib/acfs/model/query_methods.rb +66 -0
  21. data/lib/acfs/model/relations.rb +10 -0
  22. data/lib/acfs/model/service.rb +29 -0
  23. data/lib/acfs/request.rb +33 -0
  24. data/lib/acfs/request/callbacks.rb +46 -0
  25. data/lib/acfs/response.rb +21 -0
  26. data/lib/acfs/response/formats.rb +12 -0
  27. data/lib/acfs/service.rb +30 -0
  28. data/lib/acfs/version.rb +1 -1
  29. data/spec/acfs/middleware/json_decoder_spec.rb +45 -0
  30. data/spec/acfs/request/callbacks_spec.rb +34 -0
  31. data/spec/acfs/request_spec.rb +71 -0
  32. data/spec/acfs_spec.rb +69 -0
  33. data/spec/{attributes_spec.rb → model/attributes_spec.rb} +25 -12
  34. data/spec/model/initialization_spec.rb +30 -0
  35. data/spec/model/locatable_spec.rb +15 -0
  36. data/spec/service_spec.rb +37 -0
  37. data/spec/spec_helper.rb +2 -0
  38. data/spec/support/service.rb +24 -0
  39. metadata +89 -23
  40. data/lib/acfs/attributes/integer.rb +0 -15
  41. data/lib/acfs/attributes/string.rb +0 -15
  42. data/lib/acfs/client.rb +0 -15
  43. data/spec/client_spec.rb +0 -12
  44. data/spec/initialization_spec.rb +0 -22
  45. data/spec/support/my_client.rb +0 -12
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Acfs::Request do
4
+ let(:url) { 'http://api.example.org/v1/examples' }
5
+ let(:headers) { nil }
6
+ let(:params) { nil }
7
+ let(:data) { nil }
8
+ let(:options) { {headers: headers, params: params, data: data} }
9
+ let(:request) { Acfs::Request.new(url, options) }
10
+
11
+ describe '#url' do
12
+ it 'should return request URL' do
13
+ expect(request.url).to be == url
14
+ end
15
+
16
+ context 'with parameters' do
17
+ let(:params) { { id: 10 }}
18
+
19
+ it 'should return URL without query' do
20
+ expect(request.url).to be == "#{url}"
21
+ end
22
+ end
23
+
24
+ context 'with parameters in URL' do
25
+ let(:url) { 'http://api.example.org/v1/examples?b=ac' }
26
+ let(:params) { { id: 10 }}
27
+
28
+ it 'should strip query from URL' do
29
+ expect(request.url).to be == 'http://api.example.org/v1/examples'
30
+ end
31
+ end
32
+ end
33
+
34
+ describe '#headers' do
35
+ let(:headers) { { 'Accept' => 'application/json' } }
36
+
37
+ it 'should return request headers' do
38
+ expect(request.headers).to be == headers
39
+ end
40
+ end
41
+
42
+ describe '#params' do
43
+ let(:params) { { id: 10 }}
44
+
45
+ it 'should return request headers' do
46
+ expect(request.params).to be == params
47
+ end
48
+ end
49
+
50
+ describe '#data' do
51
+ let(:data) { { id: 10, name: 'Anon' } }
52
+
53
+ it 'should return request data' do
54
+ expect(request.data).to be == data
55
+ end
56
+ end
57
+
58
+ describe '#data' do
59
+ context 'with data' do
60
+ let(:data) { { id: 10, name: 'Anon' } }
61
+
62
+ it { expect(request).to be_data }
63
+ end
64
+
65
+ context 'without data' do
66
+ let(:data) { nil }
67
+
68
+ it { expect(request).to_not be_data }
69
+ end
70
+ end
71
+ end
data/spec/acfs_spec.rb ADDED
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Acfs" do
4
+
5
+ before do
6
+ Acfs.use Acfs::Middleware::JsonDecoder
7
+
8
+ headers = { 'Content-Type' => 'application/json' }
9
+ stub_request(:get, "http://users.example.org/users").to_return(:body => '[{"id":1,"name":"Anon","age":12},{"id":2,"name":"John","age":26}]', headers: headers)
10
+ stub_request(:get, "http://users.example.org/users/2").to_return(:body => '{"id":2,"name":"John","age":26}', headers: headers)
11
+ stub_request(:get, "http://users.example.org/users/2/friends").to_return(:body => '[{"id":1,"name":"Anon","age":12}]', headers: headers)
12
+ stub_request(:get, "http://comments.example.org/comments?user=2").to_return(:body => '[{"id":1,"text":"Comment #1"},{"id":2,"text":"Comment #2"}]', headers: headers)
13
+ end
14
+
15
+ it 'should load single resource' do
16
+ @user = MyUser.find(2)
17
+
18
+ expect(@user).to_not be_loaded
19
+
20
+ Acfs.run
21
+
22
+ expect(@user).to be_loaded
23
+ expect(@user.name).to be == 'John'
24
+ expect(@user.age).to be == 26
25
+ end
26
+
27
+ it 'should load multiple resources' do
28
+ @users = MyUser.all
29
+
30
+ expect(@users).to_not be_loaded
31
+
32
+ Acfs.run
33
+
34
+ expect(@users).to be_loaded
35
+ expect(@users).to have(2).items
36
+ expect(@users[0].name).to be == 'Anon'
37
+ expect(@users[0].age).to be == 12
38
+ expect(@users[1].name).to be == 'John'
39
+ expect(@users[1].age).to be == 26
40
+ end
41
+
42
+ it 'should load associated resources' do
43
+ pending "TODO: Implement high level feature"
44
+
45
+ @user = MyUser.find(2) do |user|
46
+ @friends = user.friends.all
47
+ end
48
+
49
+ Acfs.run
50
+
51
+ expect(@user.name).to be == 'John'
52
+ expect(@user.age).to be == 26
53
+
54
+ expect(@friends).to have(1).items
55
+ end
56
+
57
+ it 'should load associated resources from different service' do
58
+ @user = MyUser.find(2) do |user|
59
+ @comments = Comment.where user: user.id
60
+ end
61
+
62
+ Acfs.run
63
+
64
+ expect(@user.name).to be == 'John'
65
+ expect(@user.age).to be == 26
66
+
67
+ expect(@comments).to have(2).items
68
+ end
69
+ end
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Acfs::Attributes do
4
- let(:model) { Class.new(MyModel) }
3
+ describe Acfs::Model::Attributes do
4
+ let(:model) { Class.new.tap { |c| c.send :include, Acfs::Model }}
5
5
 
6
6
  describe '#initialize' do
7
- before { model.send :attribute, :name, default: 'John' }
7
+ before { model.attribute :name, :string, default: 'John' }
8
8
 
9
9
  it 'should have attribute list' do
10
10
  expect(model.new.attributes).to include('name')
@@ -17,8 +17,8 @@ describe Acfs::Attributes do
17
17
 
18
18
  describe '#attributes' do
19
19
  before do
20
- model.send :attribute, :name, default: 'John'
21
- model.send :attribute, :age, type: :integer, default: 25
20
+ model.attribute :name, :string, default: 'John'
21
+ model.attribute :age, :integer, default: 25
22
22
  end
23
23
 
24
24
  it 'should return hash of all attributes' do
@@ -30,10 +30,13 @@ describe Acfs::Attributes do
30
30
  end
31
31
 
32
32
  describe '#_getter_' do
33
- before { model.send :attribute, :name, default: 'John' }
33
+ before { model.attribute :name, :string, default: 'John' }
34
34
 
35
35
  it 'should return value' do
36
- expect(model.new(name: 'Paul').name).to be == 'Paul'
36
+ mo = model.new
37
+ mo.name = 'Paul'
38
+
39
+ expect(mo.name).to be == 'Paul'
37
40
  end
38
41
 
39
42
  it 'should return default value' do
@@ -49,7 +52,10 @@ describe Acfs::Attributes do
49
52
  end
50
53
 
51
54
  describe '#_setter_' do
52
- before { model.send :attribute, :name, default: 'John' }
55
+ before do
56
+ model.attribute :name, :string, default: 'John'
57
+ model.attribute :age, :integer, default: '25'
58
+ end
53
59
 
54
60
  it 'should set value' do
55
61
  o = model.new
@@ -71,29 +77,36 @@ describe Acfs::Attributes do
71
77
 
72
78
  expect(o.attributes['name']).to be == 'Johannes'
73
79
  end
80
+
81
+ it 'should cast values' do
82
+ o = model.new
83
+ o.age = "28"
84
+
85
+ expect(o.age).to be == 28
86
+ end
74
87
  end
75
88
 
76
89
  describe '.attribute' do
77
90
  it 'should add an attribute to model attribute list' do
78
- model.send :attribute, :name
91
+ model.send :attribute, :name, :string
79
92
 
80
93
  expect(model.attributes).to be == { :name => '' }
81
94
  end
82
95
 
83
96
  it 'should accept a default value' do
84
- model.send :attribute, :name, default: 'John'
97
+ model.send :attribute, :name, :string, default: 'John'
85
98
 
86
99
  expect(model.attributes).to be == { :name => 'John' }
87
100
  end
88
101
 
89
102
  it 'should accept an symbolic type' do
90
- model.send :attribute, :age, type: :integer, default: '12'
103
+ model.send :attribute, :age, :integer, default: '12'
91
104
 
92
105
  expect(model.attributes).to be == { :age => 12 }
93
106
  end
94
107
 
95
108
  it 'should accept an class type' do
96
- model.send :attribute, :age, type: Acfs::Attributes::Integer, default: '12'
109
+ model.send :attribute, :age, Acfs::Model::Attributes::Integer, default: '12'
97
110
 
98
111
  expect(model.attributes).to be == { :age => 12 }
99
112
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Acfs::Model::Initialization' do
4
+ let(:model) do
5
+ Class.new.tap do |c|
6
+ c.class_eval do
7
+ include Acfs::Model
8
+ attr_accessor :name, :age
9
+ private :age=
10
+ end
11
+ end
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'should allow to set attributes with initializer' do
16
+ m = model.new(name: "John")
17
+ expect(m.name).to be == "John"
18
+ end
19
+
20
+ it 'should raise error when attributes with private setters are given' do
21
+ expect { model.new(age: 25) }.to raise_error(NoMethodError)
22
+ end
23
+ end
24
+
25
+ describe '#persisted?' do
26
+ it 'should be false' do
27
+ expect(model.new.persisted?).to be_false
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Acfs::Model::Locatable' do
4
+ let(:model) { MyUser }
5
+
6
+ describe '.url' do
7
+ it 'should return URL' do
8
+ expect(model.url).to be == 'http://users.example.org/users'
9
+ end
10
+
11
+ it 'should return URL with id path part if specified' do
12
+ expect(model.url(5)).to be == 'http://users.example.org/users/5'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Acfs::Service do
4
+ let(:srv_class) { Class.new(Acfs::Service) }
5
+ let(:options) { {} }
6
+ let(:service) { srv_class.new options }
7
+
8
+ describe '#initialize' do
9
+ let(:options) { { path: 'abc', key: 'value' } }
10
+
11
+ it "should set options" do
12
+ expect(service.options).to eq(options)
13
+ end
14
+ end
15
+
16
+ describe '#url_for' do
17
+ it 'should extract resource path name from given class' do
18
+ expect(service.url_for(Class)).to eq('/classes')
19
+ end
20
+
21
+ context 'with path options' do
22
+ let(:options) { { path: 'abc' } }
23
+
24
+ it 'should have custom resource path' do
25
+ expect(service.url_for(Class)).to eq('/abc')
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '.base_url' do
31
+ it "should have a static base_url configuration option" do
32
+ srv_class.base_url = 'http://abc.de/api/v1'
33
+
34
+ expect(srv_class.base_url).to eq('http://abc.de/api/v1')
35
+ end
36
+ end
37
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,8 @@ require 'acfs'
2
2
  require 'coveralls'
3
3
  Coveralls.wear!
4
4
 
5
+ require 'webmock/rspec'
6
+
5
7
  Dir[File.expand_path('spec/support/**/*.rb')].each {|f| require f}
6
8
 
7
9
  RSpec.configure do |config|
@@ -0,0 +1,24 @@
1
+
2
+ class UserService < Acfs::Service
3
+ self.base_url = 'http://users.example.org'
4
+ end
5
+
6
+ class CommentService < Acfs::Service
7
+ self.base_url = 'http://comments.example.org'
8
+ end
9
+
10
+ class MyUser
11
+ include Acfs::Model
12
+ service UserService, path: 'users'
13
+
14
+ attribute :id, :integer
15
+ attribute :name, :string, default: 'Anon'
16
+ attribute :age, :integer
17
+ end
18
+
19
+ class Comment
20
+ include Acfs::Model
21
+ service CommentService
22
+
23
+ attribute :text, :string
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-19 00:00:00.000000000 Z
12
+ date: 2013-04-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -43,6 +43,38 @@ dependencies:
43
43
  - - '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: multi_json
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: typhoeus
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: bundler
48
80
  requirement: !ruby/object:Gem::Requirement
@@ -59,6 +91,22 @@ dependencies:
59
91
  - - ~>
60
92
  - !ruby/object:Gem::Version
61
93
  version: '1.3'
94
+ - !ruby/object:Gem::Dependency
95
+ name: webmock
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1.7'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '1.7'
62
110
  - !ruby/object:Gem::Dependency
63
111
  name: rake
64
112
  requirement: !ruby/object:Gem::Requirement
@@ -135,26 +183,45 @@ files:
135
183
  - .travis.yml
136
184
  - Gemfile
137
185
  - Guardfile
138
- - LICENSE.txt
186
+ - LICENSE
139
187
  - README.md
140
188
  - Rakefile
141
189
  - acfs.gemspec
142
- - gemfiles/Gemfile.rails-3-1
143
190
  - gemfiles/Gemfile.rails-3-2
191
+ - gemfiles/Gemfile.rails-4-0
144
192
  - gemfiles/Gemfile.rails-head
145
193
  - lib/acfs.rb
146
- - lib/acfs/attributes.rb
147
- - lib/acfs/attributes/integer.rb
148
- - lib/acfs/attributes/string.rb
149
- - lib/acfs/client.rb
150
- - lib/acfs/initialization.rb
194
+ - lib/acfs/adapter/typhoeus.rb
195
+ - lib/acfs/collection.rb
196
+ - lib/acfs/middleware/base.rb
197
+ - lib/acfs/middleware/json_decoder.rb
198
+ - lib/acfs/middleware/print.rb
151
199
  - lib/acfs/model.rb
200
+ - lib/acfs/model/attributes.rb
201
+ - lib/acfs/model/attributes/integer.rb
202
+ - lib/acfs/model/attributes/string.rb
203
+ - lib/acfs/model/initialization.rb
204
+ - lib/acfs/model/loadable.rb
205
+ - lib/acfs/model/locatable.rb
206
+ - lib/acfs/model/query_methods.rb
207
+ - lib/acfs/model/relations.rb
208
+ - lib/acfs/model/service.rb
209
+ - lib/acfs/request.rb
210
+ - lib/acfs/request/callbacks.rb
211
+ - lib/acfs/response.rb
212
+ - lib/acfs/response/formats.rb
213
+ - lib/acfs/service.rb
152
214
  - lib/acfs/version.rb
153
- - spec/attributes_spec.rb
154
- - spec/client_spec.rb
155
- - spec/initialization_spec.rb
215
+ - spec/acfs/middleware/json_decoder_spec.rb
216
+ - spec/acfs/request/callbacks_spec.rb
217
+ - spec/acfs/request_spec.rb
218
+ - spec/acfs_spec.rb
219
+ - spec/model/attributes_spec.rb
220
+ - spec/model/initialization_spec.rb
221
+ - spec/model/locatable_spec.rb
222
+ - spec/service_spec.rb
156
223
  - spec/spec_helper.rb
157
- - spec/support/my_client.rb
224
+ - spec/support/service.rb
158
225
  homepage: ''
159
226
  licenses:
160
227
  - MIT
@@ -168,18 +235,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
235
  - - '>='
169
236
  - !ruby/object:Gem::Version
170
237
  version: '0'
171
- segments:
172
- - 0
173
- hash: 956482736488803723
174
238
  required_rubygems_version: !ruby/object:Gem::Requirement
175
239
  none: false
176
240
  requirements:
177
241
  - - '>='
178
242
  - !ruby/object:Gem::Version
179
243
  version: '0'
180
- segments:
181
- - 0
182
- hash: 956482736488803723
183
244
  requirements: []
184
245
  rubyforge_project:
185
246
  rubygems_version: 1.8.25
@@ -187,8 +248,13 @@ signing_key:
187
248
  specification_version: 3
188
249
  summary: An abstract API base client for service oriented application.
189
250
  test_files:
190
- - spec/attributes_spec.rb
191
- - spec/client_spec.rb
192
- - spec/initialization_spec.rb
251
+ - spec/acfs/middleware/json_decoder_spec.rb
252
+ - spec/acfs/request/callbacks_spec.rb
253
+ - spec/acfs/request_spec.rb
254
+ - spec/acfs_spec.rb
255
+ - spec/model/attributes_spec.rb
256
+ - spec/model/initialization_spec.rb
257
+ - spec/model/locatable_spec.rb
258
+ - spec/service_spec.rb
193
259
  - spec/spec_helper.rb
194
- - spec/support/my_client.rb
260
+ - spec/support/service.rb