acfs 1.3.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -1
  3. data/README.md +10 -25
  4. data/acfs.gemspec +20 -15
  5. data/lib/acfs.rb +2 -0
  6. data/lib/acfs/adapter/base.rb +6 -8
  7. data/lib/acfs/adapter/typhoeus.rb +25 -6
  8. data/lib/acfs/collection.rb +2 -1
  9. data/lib/acfs/collections/paginatable.rb +4 -3
  10. data/lib/acfs/configuration.rb +14 -7
  11. data/lib/acfs/errors.rb +60 -19
  12. data/lib/acfs/global.rb +12 -2
  13. data/lib/acfs/location.rb +9 -5
  14. data/lib/acfs/middleware/base.rb +5 -1
  15. data/lib/acfs/middleware/json.rb +5 -3
  16. data/lib/acfs/middleware/logger.rb +2 -0
  17. data/lib/acfs/middleware/msgpack.rb +2 -0
  18. data/lib/acfs/middleware/print.rb +2 -0
  19. data/lib/acfs/middleware/serializer.rb +2 -0
  20. data/lib/acfs/operation.rb +20 -3
  21. data/lib/acfs/request.rb +5 -1
  22. data/lib/acfs/request/callbacks.rb +5 -1
  23. data/lib/acfs/resource.rb +2 -0
  24. data/lib/acfs/resource/attributes.rb +5 -2
  25. data/lib/acfs/resource/attributes/base.rb +2 -1
  26. data/lib/acfs/resource/attributes/boolean.rb +2 -0
  27. data/lib/acfs/resource/attributes/date_time.rb +2 -1
  28. data/lib/acfs/resource/attributes/dict.rb +2 -0
  29. data/lib/acfs/resource/attributes/float.rb +5 -3
  30. data/lib/acfs/resource/attributes/integer.rb +2 -0
  31. data/lib/acfs/resource/attributes/list.rb +2 -0
  32. data/lib/acfs/resource/attributes/string.rb +2 -0
  33. data/lib/acfs/resource/attributes/uuid.rb +4 -3
  34. data/lib/acfs/resource/dirty.rb +2 -0
  35. data/lib/acfs/resource/initialization.rb +2 -0
  36. data/lib/acfs/resource/loadable.rb +2 -0
  37. data/lib/acfs/resource/locatable.rb +10 -6
  38. data/lib/acfs/resource/operational.rb +2 -1
  39. data/lib/acfs/resource/persistence.rb +7 -6
  40. data/lib/acfs/resource/query_methods.rb +6 -4
  41. data/lib/acfs/resource/service.rb +3 -1
  42. data/lib/acfs/resource/validation.rb +3 -1
  43. data/lib/acfs/response.rb +2 -0
  44. data/lib/acfs/response/formats.rb +2 -0
  45. data/lib/acfs/response/status.rb +3 -1
  46. data/lib/acfs/rspec.rb +2 -0
  47. data/lib/acfs/runner.rb +6 -1
  48. data/lib/acfs/service.rb +24 -13
  49. data/lib/acfs/service/middleware.rb +2 -0
  50. data/lib/acfs/service/middleware/stack.rb +5 -3
  51. data/lib/acfs/singleton_resource.rb +4 -2
  52. data/lib/acfs/stub.rb +32 -11
  53. data/lib/acfs/util.rb +2 -0
  54. data/lib/acfs/version.rb +4 -2
  55. data/lib/acfs/yard.rb +1 -0
  56. data/spec/acfs/adapter/typhoeus_spec.rb +30 -3
  57. data/spec/acfs/collection_spec.rb +7 -5
  58. data/spec/acfs/configuration_spec.rb +2 -0
  59. data/spec/acfs/global_spec.rb +50 -3
  60. data/spec/acfs/location_spec.rb +2 -0
  61. data/spec/acfs/middleware/json_spec.rb +3 -1
  62. data/spec/acfs/middleware/msgpack_spec.rb +2 -0
  63. data/spec/acfs/operation_spec.rb +2 -0
  64. data/spec/acfs/request/callbacks_spec.rb +2 -0
  65. data/spec/acfs/request_spec.rb +3 -1
  66. data/spec/acfs/resource/attributes/boolean_spec.rb +2 -0
  67. data/spec/acfs/resource/attributes/date_time_spec.rb +2 -0
  68. data/spec/acfs/resource/attributes/dict_spec.rb +4 -2
  69. data/spec/acfs/resource/attributes/float_spec.rb +3 -1
  70. data/spec/acfs/resource/attributes/integer_spec.rb +2 -0
  71. data/spec/acfs/resource/attributes/list_spec.rb +5 -3
  72. data/spec/acfs/resource/attributes/uuid_spec.rb +2 -0
  73. data/spec/acfs/resource/attributes_spec.rb +8 -8
  74. data/spec/acfs/resource/dirty_spec.rb +2 -0
  75. data/spec/acfs/resource/initialization_spec.rb +8 -2
  76. data/spec/acfs/resource/loadable_spec.rb +2 -0
  77. data/spec/acfs/resource/locatable_spec.rb +2 -0
  78. data/spec/acfs/resource/persistance_spec.rb +10 -4
  79. data/spec/acfs/resource/query_methods_spec.rb +24 -17
  80. data/spec/acfs/resource/validation_spec.rb +2 -0
  81. data/spec/acfs/response/formats_spec.rb +3 -1
  82. data/spec/acfs/response/status_spec.rb +2 -0
  83. data/spec/acfs/runner_spec.rb +6 -8
  84. data/spec/acfs/service/middleware_spec.rb +2 -0
  85. data/spec/acfs/service_spec.rb +3 -1
  86. data/spec/acfs/singleton_resource_spec.rb +2 -0
  87. data/spec/acfs/stub_spec.rb +2 -0
  88. data/spec/acfs_spec.rb +2 -0
  89. data/spec/spec_helper.rb +3 -1
  90. data/spec/support/hash.rb +2 -0
  91. data/spec/support/response.rb +2 -0
  92. data/spec/support/service.rb +1 -0
  93. data/spec/support/shared/find_callbacks.rb +2 -0
  94. metadata +13 -28
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # YARD macros
2
3
 
3
4
  # @!macro [new] experimental
@@ -1,14 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Adapter::Typhoeus do
4
6
  let(:adapter) { described_class.new }
5
- before { WebMock.allow_net_connect! }
7
+
8
+ before do
9
+ stub_request(:any, 'http://example.org').to_return status: 200
10
+ end
6
11
 
7
12
  it 'raises an error' do
8
- request1 = Acfs::Request.new 'http://altimos.de/404.1' do |_rsp|
13
+ request1 = Acfs::Request.new 'http://example.org' do |_rsp|
9
14
  raise '404-1'
10
15
  end
11
- request2 = Acfs::Request.new 'http://altimos.de/404.2' do |_rsp|
16
+ request2 = Acfs::Request.new 'http://example.org' do |_rsp|
12
17
  raise '404-2'
13
18
  end
14
19
  adapter.queue request1
@@ -18,6 +23,28 @@ describe Acfs::Adapter::Typhoeus do
18
23
  expect { adapter.start }.to_not raise_error
19
24
  end
20
25
 
26
+ it 'raises timeout' do
27
+ stub_request(:any, 'http://example.org').to_timeout
28
+
29
+ request = Acfs::Request.new 'http://example.org'
30
+ adapter.queue request
31
+
32
+ expect { adapter.run(request) }.to raise_error(::Acfs::TimeoutError) do |err|
33
+ expect(err.message).to eq 'Timeout reached: GET http://example.org'
34
+ end
35
+ end
36
+
37
+ it 'raises connection errors' do
38
+ WebMock.allow_net_connect!
39
+
40
+ request = Acfs::Request.new 'http://should-never-exists.example.org'
41
+ adapter.queue request
42
+
43
+ expect { adapter.run(request) }.to raise_error(::Acfs::RequestError) do |err|
44
+ expect(err.message).to eq 'Couldn\'t resolve host name: GET http://should-never-exists.example.org'
45
+ end
46
+ end
47
+
21
48
  it 'passes arguments to typhoeus hydra' do
22
49
  value = {key: 1, key2: 2}
23
50
 
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Collection do
4
6
  let(:model) { MyUser }
5
7
 
6
8
  describe 'Pagination' do
7
- let(:params) { Hash.new }
9
+ let(:params) { {} }
8
10
  let!(:collection) { model.all params }
9
11
 
10
12
  subject { Acfs.run; collection }
@@ -62,7 +64,7 @@ describe Acfs::Collection do
62
64
  .to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
63
65
  headers: {
64
66
  'X-Total-Pages' => '2',
65
- 'Link' => '<http://users.example.org/users?page=2>; rel="next"'
67
+ 'Link' => '<http://users.example.org/users?page=2>; rel="next"'
66
68
  })
67
69
  end
68
70
  let!(:req) do
@@ -86,7 +88,7 @@ describe Acfs::Collection do
86
88
  .to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
87
89
  headers: {
88
90
  'X-Total-Pages' => '2',
89
- 'Link' => '<http://users.example.org/users>; rel="prev"'
91
+ 'Link' => '<http://users.example.org/users>; rel="prev"'
90
92
  })
91
93
  end
92
94
  let!(:req) do
@@ -110,7 +112,7 @@ describe Acfs::Collection do
110
112
  .to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
111
113
  headers: {
112
114
  'X-Total-Pages' => '2',
113
- 'Link' => '<http://users.example.org/users>; rel="first"'
115
+ 'Link' => '<http://users.example.org/users>; rel="first"'
114
116
  })
115
117
  end
116
118
  let!(:req) do
@@ -134,7 +136,7 @@ describe Acfs::Collection do
134
136
  .to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
135
137
  headers: {
136
138
  'X-Total-Pages' => '2',
137
- 'Link' => '<http://users.example.org/users?page=12>; rel="last"'
139
+ 'Link' => '<http://users.example.org/users?page=12>; rel="last"'
138
140
  })
139
141
  end
140
142
  let!(:req) do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Configuration do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  class NotificationCollector
@@ -48,7 +50,8 @@ describe ::Acfs::Global do
48
50
  stub_request(:get, %r{http://users.example.org/users/\d+}).to_return(
49
51
  status: 200,
50
52
  body: '{}',
51
- headers: {'Content-Type' => 'application/json'})
53
+ headers: {'Content-Type' => 'application/json'}
54
+ )
52
55
  end
53
56
 
54
57
  it 'should invoke when both resources' do
@@ -71,12 +74,56 @@ describe ::Acfs::Global do
71
74
  end
72
75
  Acfs.run
73
76
  end
77
+
78
+ context 'with an empty result for a find_by call' do
79
+ before do
80
+ stub_request(:get, %r{http://users.example.org/users})
81
+ .with(query: {id: '2'})
82
+ .to_return(
83
+ status: 200,
84
+ body: '{}',
85
+ headers: {'Content-Type' => 'application/json'}
86
+ )
87
+ end
88
+
89
+ it 'invokes once both requests are finished' do
90
+ user1 = MyUser.find 1
91
+ user2 = MyUser.find_by id: 2
92
+
93
+ expect do |cb|
94
+ Acfs.on(user1, user2, &cb)
95
+ Acfs.run
96
+ end.to yield_with_args(user1, be_nil)
97
+ end
98
+
99
+ it 'invokes once remaining requests are finished' do
100
+ user1 = MyUser.find 1
101
+ Acfs.run # Finish the first request
102
+
103
+ user2 = MyUser.find_by id: 2
104
+
105
+ expect do |cb|
106
+ Acfs.on(user1, user2, &cb)
107
+ Acfs.run
108
+ end.to yield_with_args(user1, be_nil)
109
+ end
110
+
111
+ it 'invokes immediately when all requests have already been finished' do
112
+ user1 = MyUser.find 1
113
+ user2 = MyUser.find_by id: 2
114
+ Acfs.run
115
+
116
+ expect do |cb|
117
+ Acfs.on(user1, user2, &cb)
118
+ end.to yield_with_args(user1, be_nil)
119
+ end
120
+ end
74
121
  end
75
122
 
76
123
  describe '#runner' do
77
124
  it 'returns per-thread runner' do
78
- runner1 = Thread.new { acfs.runner } .value
79
- runner2 = Thread.new { acfs.runner } .value
125
+ runner1 = Thread.new { acfs.runner }.value
126
+ runner2 = Thread.new { acfs.runner }.value
80
127
 
81
128
  expect(runner1).to_not equal runner2
82
129
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ::Acfs::Location do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Middleware::JSON do
@@ -45,7 +47,7 @@ describe Acfs::Middleware::JSON do
45
47
  let(:body) { data.to_json[4..-4] }
46
48
 
47
49
  it 'should raise an error' do
48
- expect { request.complete! response }.to raise_error(MultiJson::LoadError)
50
+ expect { request.complete! response }.to raise_error(::JSON::ParserError)
49
51
  end
50
52
  end
51
53
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Middleware::MessagePack do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ::Acfs::Operation do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Request::Callbacks do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Request do
@@ -18,7 +20,7 @@ describe Acfs::Request do
18
20
  let(:params) { {id: 10} }
19
21
 
20
22
  it 'should return URL without query' do
21
- expect(request.url).to be == "#{url}"
23
+ expect(request.url).to be == url.to_s
22
24
  end
23
25
  end
24
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::Boolean do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::DateTime do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::Dict do
@@ -13,12 +15,12 @@ describe Acfs::Resource::Attributes::Dict do
13
15
 
14
16
  context 'with blank string (I)' do
15
17
  let(:value) { '' }
16
- it { expect(subject.call).to eq Hash.new }
18
+ it { expect(subject.call).to eq({}) }
17
19
  end
18
20
 
19
21
  context 'with blank string (II)' do
20
22
  let(:value) { " \t" }
21
- it { expect(subject.call).to eq Hash.new }
23
+ it { expect(subject.call).to eq({}) }
22
24
  end
23
25
 
24
26
  context 'with hash' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::Float do
@@ -33,7 +35,7 @@ describe Acfs::Resource::Attributes::Float do
33
35
 
34
36
  context 'with -Infinity' do
35
37
  let(:value) { '-Infinity' }
36
- it { expect(subject.call).to eq -::Float::INFINITY }
38
+ it { expect(subject.call).to eq(-::Float::INFINITY) }
37
39
  end
38
40
 
39
41
  context 'with NaN' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::Integer do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::List do
@@ -13,16 +15,16 @@ describe Acfs::Resource::Attributes::List do
13
15
 
14
16
  context 'with blank string (I)' do
15
17
  let(:value) { '' }
16
- it { expect(subject.call).to eq Array.new }
18
+ it { expect(subject.call).to eq [] }
17
19
  end
18
20
 
19
21
  context 'with blank string (II)' do
20
22
  let(:value) { " \t" }
21
- it { expect(subject.call).to eq Array.new }
23
+ it { expect(subject.call).to eq [] }
22
24
  end
23
25
 
24
26
  context 'with array' do
25
- let(:value) { %w(abc cde efg) }
27
+ let(:value) { %w[abc cde efg] }
26
28
  it { expect(subject.call).to eq value }
27
29
  end
28
30
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes::UUID do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Attributes do
@@ -52,7 +54,7 @@ describe Acfs::Resource::Attributes do
52
54
  let(:action) { -> { m.write_attributes(*args) } }
53
55
  subject { action }
54
56
 
55
- it 'should update attributes' do
57
+ it 'should update attributes' do
56
58
  should change(m, :attributes)
57
59
  .from(name: 'The Great John', age: 25)
58
60
  .to(name: 'The Great James', age: 25)
@@ -70,7 +72,7 @@ describe Acfs::Resource::Attributes do
70
72
 
71
73
  it { should_not raise_error }
72
74
 
73
- it 'should update known attributes and store unknown' do
75
+ it 'should update known attributes and store unknown' do
74
76
  should change(m, :attributes)
75
77
  .from(name: 'The Great John', age: 25)
76
78
  .to(name: 'The Great James', age: 25, born_at: 'today')
@@ -83,11 +85,9 @@ describe Acfs::Resource::Attributes do
83
85
 
84
86
  it do
85
87
  expect do
86
- begin
87
- subject.call
88
- rescue
89
- true
90
- end
88
+ subject.call
89
+ rescue StandardError
90
+ true
91
91
  end.to_not change(m, :attributes)
92
92
  end
93
93
  end
@@ -171,7 +171,7 @@ describe Acfs::Resource::Attributes do
171
171
  end
172
172
 
173
173
  it 'includes superclass attributes' do
174
- expect(submodel.attributes.keys).to match_array %w(age born_at)
174
+ expect(submodel.attributes.keys).to match_array %w[age born_at]
175
175
  end
176
176
  end
177
177
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Dirty do
@@ -1,11 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe 'Acfs::Resource::Initialization' do
4
6
  let(:model) do
5
7
  Class.new(Acfs::Resource).tap do |c|
6
8
  c.class_eval do
7
- attr_accessor :name, :age
8
- private :age=
9
+ attr_accessor :name
10
+ attr_reader :age
11
+
12
+ private
13
+
14
+ attr_writer :age
9
15
  end
10
16
  end
11
17
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Loadable do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Locatable do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Acfs::Resource::Persistence do
@@ -226,8 +228,12 @@ describe Acfs::Resource::Persistence do
226
228
 
227
229
  it 'should set local errors hash' do
228
230
  model.name = ''
229
- model.save! rescue nil
230
- expect(model.errors.to_hash).to be == {name: %w(required)}
231
+ begin
232
+ model.save!
233
+ rescue StandardError
234
+ nil
235
+ end
236
+ expect(model.errors.to_hash).to be == {name: %w[required]}
231
237
  end
232
238
  end
233
239
 
@@ -265,7 +271,7 @@ describe Acfs::Resource::Persistence do
265
271
  it 'should raise an error' do
266
272
  expect { model_class.create! data }.to \
267
273
  raise_error(::Acfs::InvalidResource) do |error|
268
- expect(error.errors).to be == {'name' => %w(required)}
274
+ expect(error.errors).to be == {'name' => %w[required]}
269
275
  end
270
276
  end
271
277
  end
@@ -295,7 +301,7 @@ describe Acfs::Resource::Persistence do
295
301
  end
296
302
 
297
303
  it 'should contain error hash' do
298
- expect(subject.errors.to_hash).to eq name: %w(required)
304
+ expect(subject.errors.to_hash).to eq name: %w[required]
299
305
  end
300
306
  end
301
307