acfs 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9983fabc6b3c91e17cf08ac15da6e51aecf584b5
4
- data.tar.gz: 53f6525a13c507bd7cac8132d2618a2b92e551ca
3
+ metadata.gz: 69903ec6f49f6fb0d192c60aa302ddc9ba16f940
4
+ data.tar.gz: bb15a106632b4d5f3681d829bee1b4e547d61039
5
5
  SHA512:
6
- metadata.gz: 7869d4338121f188461dd2e2b4383f1175ebec3255e868a36cd53c63df31cbf6bb746135c8aaddebefb3f3ec5185e565606330a23ebcd75f3f4f838a94ec3591
7
- data.tar.gz: d9c7a0575f86fd9e2b71fc98336166aef3e770e82fe6c7f5365b7751eeee78a987fa8eb433b326e228ceccc62c2daba610268664594b5992127911676f5aa735
6
+ metadata.gz: 4acac2d53426422d60c59502fde95f17893fabced18c70d9236c3473c1250be5ac492f8ff6271db2073340af96725dee05748a6a5de43d9f92fa330fb3ef060d
7
+ data.tar.gz: d4aefee793caaad3a20afcc1c703b07882492805ad80ce70efb9fafda71700f425ed2246e8964e03c839cfd1f9ebe6da255872316afceabe15bea413161ad518
data/README.md CHANGED
@@ -13,7 +13,7 @@ level and automatic request queuing and parallel processing. See Usage for more.
13
13
 
14
14
  Add this line to your application's Gemfile:
15
15
 
16
- gem 'acfs', '~> 0.10.0'
16
+ gem 'acfs', '~> 0.11.0'
17
17
 
18
18
  **Note:** Acfs is under development. I'll try to avoid changes to the public
19
19
  API but internal APIs may change quite often.
@@ -17,6 +17,7 @@ module Acfs
17
17
 
18
18
  autoload :Base
19
19
  autoload :Print
20
+ autoload :Logger
20
21
  autoload :JsonDecoder
21
22
  autoload :MessagePackDecoder, 'acfs/middleware/msgpack_decoder'
22
23
  autoload :JsonEncoder
@@ -21,6 +21,12 @@ module Acfs
21
21
  hydra.queue convert_request(req)
22
22
  end
23
23
 
24
+ # Remove all requests from queue.
25
+ #
26
+ def clear
27
+ hydra.abort
28
+ end
29
+
24
30
  protected
25
31
  def hydra
26
32
  @hydra ||= ::Typhoeus::Hydra.new
@@ -41,7 +47,10 @@ module Acfs
41
47
  end
42
48
 
43
49
  def convert_response(request, response)
44
- Acfs::Response.new(request, response.code, response.headers, response.body)
50
+ Acfs::Response.new request,
51
+ status: response.code,
52
+ headers: response.headers,
53
+ body: response.body
45
54
  end
46
55
  end
47
56
  end
@@ -2,6 +2,22 @@ module Acfs
2
2
 
3
3
  # Acfs base error.
4
4
  #
5
- class Error < StandardError; end
5
+ class Error < StandardError
6
+ end
7
+
8
+ # Response error containing the responsible response object.
9
+ #
10
+ class ErroneousResponse < Error
11
+ attr_accessor :response
12
+
13
+ def initialize(response)
14
+ self.response = response
15
+ end
16
+ end
17
+
18
+ # Resource not found error raised on a 404 response
19
+ #
20
+ class ResourceNotFound < ErroneousResponse
21
+ end
6
22
 
7
23
  end
@@ -0,0 +1,25 @@
1
+ require 'logger'
2
+
3
+ module Acfs
4
+ module Middleware
5
+
6
+ # Log requests and responses.
7
+ #
8
+ class Logger < Base
9
+
10
+ def initialize(app, options = {})
11
+ super
12
+ @logger = options[:logger] if options[:logger]
13
+ end
14
+
15
+ def response(res, nxt)
16
+ logger.info "[ACFS] #{res.request.method.to_s.upcase} #{res.request.url} -> #{res.status}"
17
+ nxt.call res
18
+ end
19
+
20
+ def logger
21
+ @logger ||= ::Logger.new STDOUT
22
+ end
23
+ end
24
+ end
25
+ end
@@ -73,7 +73,7 @@ module Acfs::Model
73
73
  #
74
74
  def write_attribute(name, value, opts = {})
75
75
  if (type = self.class.attribute_types[name.to_sym]).nil?
76
- raise "Unknown attribute #{name}."
76
+ raise "Unknown attribute `#{name}`."
77
77
  end
78
78
 
79
79
  write_raw_attribute name, value.nil? ? nil : type.cast(value), opts
@@ -58,9 +58,13 @@ module Acfs::Model
58
58
  model = self.new
59
59
 
60
60
  request = Acfs::Request.new url(id.to_s) do |response|
61
- model.attributes = response.data
62
- model.loaded!
63
- block.call model unless block.nil?
61
+ if response.success?
62
+ model.attributes = response.data
63
+ model.loaded!
64
+ block.call model unless block.nil?
65
+ else
66
+ raise_error_for response
67
+ end
64
68
  end
65
69
  service.queue request
66
70
 
@@ -81,6 +85,15 @@ module Acfs::Model
81
85
  end
82
86
  end
83
87
  end
88
+
89
+ def raise_error_for(response)
90
+ case response.code
91
+ when 404
92
+ raise ::Acfs::ResourceNotFound.new response
93
+ else
94
+ raise ::Acfs::ErroneousResponse.new response
95
+ end
96
+ end
84
97
  end
85
98
  end
86
99
  end
@@ -1,4 +1,6 @@
1
1
  require 'acfs/response/formats'
2
+ require 'acfs/response/status'
3
+ require 'active_support/core_ext/module/delegation'
2
4
 
3
5
  module Acfs
4
6
 
@@ -7,15 +9,20 @@ module Acfs
7
9
  #
8
10
  class Response
9
11
  attr_accessor :data
10
- attr_reader :request, :status, :headers, :body
12
+ attr_reader :headers, :body
11
13
 
12
14
  include Response::Formats
15
+ include Response::Status
13
16
 
14
- def initialize(request, status = 200, headers = {}, body = nil)
15
- @request = request
16
- @status = status
17
- @headers = headers
18
- @body = body
17
+ #delegate :status, :status_message, :success?, :modified?, :timed_out?,
18
+ # :response_body, :response_headers, :response_code, :headers,
19
+ # to: :response
20
+
21
+ def initialize(request, data = {})
22
+ @request = request
23
+ @status = data[:status]
24
+ @headers = data[:headers]
25
+ @body = data[:body]
19
26
  end
20
27
  end
21
28
  end
@@ -0,0 +1,33 @@
1
+ module Acfs
2
+ class Response
3
+
4
+ # Method to fetch information about response status.
5
+ #
6
+ module Status
7
+
8
+ # Return response status code. Will return zero if
9
+ # request was not executed or failed on client side.
10
+ #
11
+ def status_code
12
+ return @status.to_i if defined? :@status
13
+ #return response.response_code unless response.nil?
14
+ #0
15
+ end
16
+ alias :code :status_code
17
+
18
+ # Return true if response was successful indicated by
19
+ # response status code.
20
+ #
21
+ def success?
22
+ code >= 200 && code < 300
23
+ end
24
+
25
+ # Return true unless response status code indicates that
26
+ # resource was not modified according to send precondition headers.
27
+ #
28
+ def modified?
29
+ code != 304
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,7 +1,7 @@
1
1
  module Acfs
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 10
4
+ MINOR = 11
5
5
  PATCH = 0
6
6
  STAGE = nil
7
7
 
@@ -5,7 +5,7 @@ describe Acfs::Middleware::JsonDecoder do
5
5
  let(:body) { data.to_param }
6
6
  let(:headers) { {} }
7
7
  let(:request) { Acfs::Request.new "fubar" }
8
- let(:response) { Acfs::Response.new request, 200, headers, body }
8
+ let(:response) { Acfs::Response.new request, status: 200, headers: headers, body: body }
9
9
  let(:decoder) { Acfs::Middleware::JsonDecoder.new lambda { |req| req } }
10
10
 
11
11
  before do
@@ -5,7 +5,7 @@ describe Acfs::Middleware::MessagePackDecoder do
5
5
  let(:body) { data.to_param }
6
6
  let(:headers) { {} }
7
7
  let(:request) { Acfs::Request.new "fubar" }
8
- let(:response) { Acfs::Response.new request, 200, headers, body }
8
+ let(:response) { Acfs::Response.new request, status: 200, headers: headers, body: body }
9
9
  let(:decoder) { Acfs::Middleware::MessagePackDecoder.new lambda { |req| req } }
10
10
 
11
11
  before do
@@ -5,28 +5,63 @@ describe Acfs::Model::QueryMethods do
5
5
 
6
6
  describe '.find' do
7
7
  context 'with single id' do
8
- before do
9
- stub_request(:get, 'http://users.example.org/users/1').to_return(
10
- body: MessagePack.dump({ id: 1, name: 'Anon', age: 12 }),
11
- headers: {'Content-Type' => 'application/x-msgpack'})
8
+ context 'with successful response' do
9
+ before do
10
+ stub_request(:get, 'http://users.example.org/users/1').to_return(
11
+ body: MessagePack.dump({ id: 1, name: 'Anon', age: 12 }),
12
+ headers: {'Content-Type' => 'application/x-msgpack'})
13
+ end
14
+
15
+ it 'should load a single remote resource' do
16
+ user = model.find 1
17
+ Acfs.run
18
+
19
+ expect(user.attributes).to be == { id: 1, name: 'Anon', age: 12 }.stringify_keys
20
+ end
21
+
22
+ it 'should invoke callback after model is loaded' do
23
+ proc = Proc.new { }
24
+ proc.should_receive(:call) do |user|
25
+ expect(user).to be === @user
26
+ expect(user).to be_loaded
27
+ end
28
+
29
+ @user = model.find 1, &proc
30
+ Acfs.run
31
+ end
12
32
  end
13
33
 
14
- it 'should load a single remote resource' do
15
- user = model.find 1
16
- Acfs.run
34
+ context 'with 404 response' do
35
+ before do
36
+ stub_request(:get, 'http://users.example.org/users/1').to_return(
37
+ status: 404,
38
+ body: MessagePack.dump({ error: 'not found' }),
39
+ headers: {'Content-Type' => 'application/x-msgpack'})
40
+ end
41
+
42
+ it 'should raise a NotFound error' do
43
+ @user = model.find 1
17
44
 
18
- expect(user.attributes).to be == { id: 1, name: 'Anon', age: 12 }.stringify_keys
45
+ expect { Acfs.run }.to raise_error(Acfs::ResourceNotFound)
46
+
47
+ expect(@user).to_not be_loaded
48
+ end
19
49
  end
20
50
 
21
- it 'should invoke callback after model is loaded' do
22
- proc = Proc.new { }
23
- proc.should_receive(:call) do |user|
24
- expect(user).to be === @user
25
- expect(user).to be_loaded
51
+ context 'with 500 response' do
52
+ before do
53
+ stub_request(:get, 'http://users.example.org/users/1').to_return(
54
+ status: 500,
55
+ headers: {'Content-Type' => 'text/plain'})
26
56
  end
27
57
 
28
- @user = model.find 1, &proc
29
- Acfs.run
58
+ it 'should raise a response error' do
59
+ @user = model.find 1
60
+
61
+ expect { Acfs.run }.to raise_error(Acfs::ErroneousResponse)
62
+
63
+ expect(@user).to_not be_loaded
64
+ end
30
65
  end
31
66
  end
32
67
 
@@ -40,25 +75,42 @@ describe Acfs::Model::QueryMethods do
40
75
  headers: {'Content-Type' => 'application/x-msgpack'})
41
76
  end
42
77
 
43
- it 'should load a multiple remote resources' do
44
- users = model.find 1, 2
45
- Acfs.run
78
+ context 'with successful response' do
79
+ it 'should load a multiple remote resources' do
80
+ users = model.find 1, 2
81
+ Acfs.run
46
82
 
47
- expect(users.size).to be == 2
48
- expect(users[0].attributes).to be == { id: 1, name: 'Anon', age: 12 }.stringify_keys
49
- expect(users[1].attributes).to be == { id: 2, name: 'Johnny', age: 42 }.stringify_keys
83
+ expect(users.size).to be == 2
84
+ expect(users[0].attributes).to be == { id: 1, name: 'Anon', age: 12 }.stringify_keys
85
+ expect(users[1].attributes).to be == { id: 2, name: 'Johnny', age: 42 }.stringify_keys
86
+ end
87
+
88
+ it 'should invoke callback after all models are loaded' do
89
+ proc = Proc.new { }
90
+ proc.should_receive(:call) do |users|
91
+ expect(users).to be === @users
92
+ expect(users.size).to be == 2
93
+ expect(users).to be_loaded
94
+ end
95
+
96
+ @users = model.find 1, 2, &proc
97
+ Acfs.run
98
+ end
50
99
  end
51
100
 
52
- it 'should invoke callback after all models are loaded' do
53
- proc = Proc.new { }
54
- proc.should_receive(:call) do |users|
55
- expect(users).to be === @users
56
- expect(users.size).to be == 2
57
- expect(users).to be_loaded
101
+ context 'with one 404 response' do
102
+ before do
103
+ stub_request(:get, 'http://users.example.org/users/1').to_return(
104
+ status: 404,
105
+ body: MessagePack.dump({ error: 'not found' }),
106
+ headers: {'Content-Type' => 'application/x-msgpack'})
58
107
  end
59
108
 
60
- @users = model.find 1, 2, &proc
61
- Acfs.run
109
+ it 'should raise resource not found error' do
110
+ model.find 1, 2
111
+
112
+ expect { Acfs.run }.to raise_error(Acfs::ResourceNotFound)
113
+ end
62
114
  end
63
115
  end
64
116
  end
@@ -6,7 +6,7 @@ describe Acfs::Response::Formats do
6
6
  let(:headers) { { 'Content-Type' => mime_type } }
7
7
  let(:request) { Acfs::Request.new 'fubar' }
8
8
  let(:body) { nil }
9
- let(:response) { Acfs::Response.new request, status, headers, body }
9
+ let(:response) { Acfs::Response.new request, status: status, headers: headers, body: body }
10
10
 
11
11
  context 'without Content-Type header' do
12
12
  let(:headers) { {} }
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Acfs::Response::Status do
4
+ let(:status) { 200 }
5
+ let(:mime_type) { 'application/unknown' }
6
+ let(:headers) { { 'Content-Type' => mime_type } }
7
+ let(:request) { Acfs::Request.new 'fubar' }
8
+ let(:body) { nil }
9
+ let(:response) { Acfs::Response.new request, status: status, headers: headers, body: body }
10
+
11
+ describe '#status_code alias #code' do
12
+ context 'when given' do
13
+ let(:status) { 200 }
14
+
15
+ it 'should return status code' do
16
+ expect(response.code).to be == 200
17
+ expect(response.status_code).to be == 200
18
+ end
19
+ end
20
+
21
+ context 'when nil' do
22
+ let(:status) { nil }
23
+
24
+ it 'should return zero' do
25
+ expect(response.code).to be == 0
26
+ expect(response.status_code).to be == 0
27
+ end
28
+ end
29
+ end
30
+
31
+ describe '#success?' do
32
+ context 'with success status code' do
33
+ let(:status) { 200 }
34
+ it { expect(response).to be_success }
35
+ end
36
+
37
+ context 'with error status code' do
38
+ let(:status) { 500 }
39
+ it { expect(response).to_not be_success }
40
+ end
41
+
42
+ context 'with zero status code' do
43
+ let(:status) { nil }
44
+ it { expect(response).to_not be_success }
45
+ end
46
+ end
47
+
48
+ describe '#modified?' do
49
+ context 'with success status code' do
50
+ let(:status) { 200 }
51
+ it { expect(response).to be_modified }
52
+ end
53
+
54
+ context 'with not modified status code' do
55
+ let(:status) { 304 }
56
+ it { expect(response).to_not be_modified }
57
+ end
58
+
59
+ context 'with error status code' do
60
+ let(:status) { 500 }
61
+ it { expect(response).to be_modified }
62
+ end
63
+
64
+ context 'with zero status code' do
65
+ let(:status) { nil }
66
+ it { expect(response).to be_modified }
67
+ end
68
+ end
69
+ end
@@ -27,4 +27,8 @@ RSpec.configure do |config|
27
27
  # Only allow expect syntax
28
28
  c.syntax = :expect
29
29
  end
30
+
31
+ config.before :each do
32
+ Acfs.adapter.clear
33
+ end
30
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-24 00:00:00.000000000 Z
11
+ date: 2013-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -204,6 +204,7 @@ files:
204
204
  - lib/acfs/middleware/base.rb
205
205
  - lib/acfs/middleware/json_decoder.rb
206
206
  - lib/acfs/middleware/json_encoder.rb
207
+ - lib/acfs/middleware/logger.rb
207
208
  - lib/acfs/middleware/msgpack_decoder.rb
208
209
  - lib/acfs/middleware/msgpack_encoder.rb
209
210
  - lib/acfs/middleware/print.rb
@@ -224,6 +225,7 @@ files:
224
225
  - lib/acfs/request/callbacks.rb
225
226
  - lib/acfs/response.rb
226
227
  - lib/acfs/response/formats.rb
228
+ - lib/acfs/response/status.rb
227
229
  - lib/acfs/service.rb
228
230
  - lib/acfs/service/middleware.rb
229
231
  - lib/acfs/service/request_handler.rb
@@ -240,6 +242,7 @@ files:
240
242
  - spec/acfs/request/callbacks_spec.rb
241
243
  - spec/acfs/request_spec.rb
242
244
  - spec/acfs/response/formats_spec.rb
245
+ - spec/acfs/response/status_spec.rb
243
246
  - spec/acfs/service_spec.rb
244
247
  - spec/acfs_spec.rb
245
248
  - spec/spec_helper.rb
@@ -281,6 +284,7 @@ test_files:
281
284
  - spec/acfs/request/callbacks_spec.rb
282
285
  - spec/acfs/request_spec.rb
283
286
  - spec/acfs/response/formats_spec.rb
287
+ - spec/acfs/response/status_spec.rb
284
288
  - spec/acfs/service_spec.rb
285
289
  - spec/acfs_spec.rb
286
290
  - spec/spec_helper.rb