acfs 1.4.0 → 1.7.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +22 -39
  4. data/acfs.gemspec +8 -14
  5. data/lib/acfs/adapter/base.rb +2 -0
  6. data/lib/acfs/adapter/typhoeus.rb +16 -11
  7. data/lib/acfs/collections/paginatable.rb +1 -1
  8. data/lib/acfs/configuration.rb +13 -3
  9. data/lib/acfs/errors.rb +41 -21
  10. data/lib/acfs/global.rb +2 -2
  11. data/lib/acfs/location.rb +26 -32
  12. data/lib/acfs/middleware/base.rb +2 -2
  13. data/lib/acfs/middleware/json.rb +4 -2
  14. data/lib/acfs/middleware/logger.rb +4 -6
  15. data/lib/acfs/middleware/serializer.rb +1 -1
  16. data/lib/acfs/operation.rb +21 -8
  17. data/lib/acfs/request/callbacks.rb +4 -4
  18. data/lib/acfs/request.rb +4 -11
  19. data/lib/acfs/resource/attributes/date_time.rb +1 -1
  20. data/lib/acfs/resource/attributes/uuid.rb +1 -1
  21. data/lib/acfs/resource/attributes.rb +16 -15
  22. data/lib/acfs/resource/dirty.rb +2 -2
  23. data/lib/acfs/resource/initialization.rb +5 -5
  24. data/lib/acfs/resource/locatable.rb +11 -8
  25. data/lib/acfs/resource/operational.rb +6 -3
  26. data/lib/acfs/resource/persistence.rb +13 -15
  27. data/lib/acfs/resource/query_methods.rb +10 -10
  28. data/lib/acfs/resource/service.rb +2 -2
  29. data/lib/acfs/resource/validation.rb +17 -7
  30. data/lib/acfs/response.rb +5 -5
  31. data/lib/acfs/runner.rb +15 -15
  32. data/lib/acfs/service.rb +16 -19
  33. data/lib/acfs/singleton_resource.rb +2 -2
  34. data/lib/acfs/stub.rb +41 -31
  35. data/lib/acfs/version.rb +2 -2
  36. data/spec/acfs/adapter/typhoeus_spec.rb +2 -2
  37. data/spec/acfs/collection_spec.rb +66 -41
  38. data/spec/acfs/configuration_spec.rb +22 -12
  39. data/spec/acfs/global_spec.rb +11 -9
  40. data/spec/acfs/location_spec.rb +2 -2
  41. data/spec/acfs/middleware/json_spec.rb +22 -8
  42. data/spec/acfs/middleware/{msgpack_spec.rb → message_pack_spec.rb} +6 -6
  43. data/spec/acfs/operation_spec.rb +3 -2
  44. data/spec/acfs/request/callbacks_spec.rb +19 -10
  45. data/spec/acfs/request_spec.rb +16 -20
  46. data/spec/acfs/resource/attributes/boolean_spec.rb +32 -32
  47. data/spec/acfs/resource/attributes/date_time_spec.rb +16 -8
  48. data/spec/acfs/resource/attributes/dict_spec.rb +15 -9
  49. data/spec/acfs/resource/attributes/float_spec.rb +20 -10
  50. data/spec/acfs/resource/attributes/integer_spec.rb +10 -5
  51. data/spec/acfs/resource/attributes/list_spec.rb +13 -8
  52. data/spec/acfs/resource/attributes/uuid_spec.rb +12 -6
  53. data/spec/acfs/resource/attributes_spec.rb +37 -38
  54. data/spec/acfs/resource/dirty_spec.rb +6 -3
  55. data/spec/acfs/resource/initialization_spec.rb +4 -5
  56. data/spec/acfs/resource/loadable_spec.rb +3 -1
  57. data/spec/acfs/resource/locatable_spec.rb +24 -18
  58. data/spec/acfs/resource/{persistance_spec.rb → persistence_spec.rb} +122 -90
  59. data/spec/acfs/resource/query_methods_spec.rb +143 -110
  60. data/spec/acfs/resource/validation_spec.rb +34 -27
  61. data/spec/acfs/response/formats_spec.rb +8 -8
  62. data/spec/acfs/response/status_spec.rb +16 -9
  63. data/spec/acfs/runner_spec.rb +10 -8
  64. data/spec/acfs/service/middleware_spec.rb +3 -3
  65. data/spec/acfs/service_spec.rb +6 -5
  66. data/spec/acfs/singleton_resource_spec.rb +2 -1
  67. data/spec/acfs/stub_spec.rb +57 -53
  68. data/spec/acfs_spec.rb +111 -93
  69. data/spec/spec_helper.rb +1 -2
  70. data/spec/support/response.rb +2 -2
  71. data/spec/support/service.rb +1 -1
  72. data/spec/support/shared/find_callbacks.rb +14 -10
  73. metadata +30 -29
@@ -4,16 +4,28 @@ require 'spec_helper'
4
4
 
5
5
  describe Acfs::Resource::Persistence do
6
6
  let(:model_class) { MyUser }
7
- before do
8
- @get_stub = stub_request(:get, 'http://users.example.org/users/1').to_return response(id: 1, name: 'Anon', age: 12)
9
7
 
10
- @patch_stub = stub_request(:put, 'http://users.example.org/users/1')
11
- .with(body: '{"id":1,"name":"Idefix","age":12}')
12
- .to_return response(id: 1, name: 'Idefix', age: 12)
8
+ let!(:patch_stub) do
9
+ stub_request(:put, 'http://users.example.org/users/1')
10
+ .with(body: '{"id":1,"name":"Idefix","age":12}')
11
+ .to_return response(id: 1, name: 'Idefix', age: 12)
12
+ end
13
13
 
14
- @post_stub = stub_request(:post, 'http://users.example.org/users')
15
- .with(body: '{"id":null,"name":"Idefix","age":12}')
16
- .to_return response(id: 5, name: 'Idefix', age: 12)
14
+ let!(:post_stub) do
15
+ stub_request(:post, 'http://users.example.org/users')
16
+ .with(body: '{"id":null,"name":"Idefix","age":12}')
17
+ .to_return response(id: 5, name: 'Idefix', age: 12)
18
+ end
19
+
20
+ let!(:delete_stub) do
21
+ stub_request(:delete, 'http://users.example.org/users/1')
22
+ .with(body: '{}')
23
+ .to_return response({id: 1, name: 'Idefix', age: 12}, {status: 200})
24
+ end
25
+
26
+ before do
27
+ stub_request(:get, 'http://users.example.org/users/1')
28
+ .to_return response(id: 1, name: 'Anon', age: 12)
17
29
 
18
30
  stub_request(:post, 'http://users.example.org/users')
19
31
  .with(body: '{"id":null,"name":"Anon","age":null}')
@@ -26,41 +38,38 @@ describe Acfs::Resource::Persistence do
26
38
  stub_request(:post, 'http://users.example.org/users')
27
39
  .with(body: '{"id":null,"name":null,"age":12}')
28
40
  .to_return response({errors: {name: ['required']}}, {status: 422})
29
-
30
- @del = stub_request(:delete, 'http://users.example.org/users/1')
31
- .with(body: '{}')
32
- .to_return response({id: 1, name: 'Idefix', age: 12}, {status: 200})
33
41
  end
34
42
 
35
43
  context 'new model' do
36
44
  let(:model) { model_class.new }
37
45
 
38
- it { expect(model).to_not be_persisted }
46
+ it { expect(model).not_to be_persisted }
39
47
  it { expect(model).to be_new }
40
48
 
41
49
  describe '#save!' do
42
50
  context 'when modified' do
43
51
  let(:model) { model_class.find 1 }
52
+
44
53
  before do
45
54
  model
46
55
  Acfs.run
47
56
  model.name = 'Idefix'
48
57
  end
49
58
 
50
- it 'should PUT to model URL' do
59
+ it 'PUTS to model URL' do
51
60
  model.save!
52
61
 
53
- expect(@patch_stub).to have_been_requested
62
+ expect(patch_stub).to have_been_requested
54
63
  end
55
64
  end
56
65
 
57
66
  context 'when new' do
58
67
  let(:model) { model_class.new name: 'Idefix', age: 12 }
59
68
 
60
- it 'should POST to collection URL' do
69
+ it 'POSTS to collection URL' do
61
70
  model.save!
62
71
 
63
- expect(@post_stub).to have_been_requested
72
+ expect(post_stub).to have_been_requested
64
73
  end
65
74
 
66
75
  context 'with unknown attributes' do
@@ -71,17 +80,17 @@ describe Acfs::Resource::Persistence do
71
80
  end
72
81
  let(:model) { model_class.new name: 'Idefix', born_at: 'Berlin' }
73
82
 
74
- it 'should POST to collection URL' do
83
+ it 'POSTS to collection URL' do
75
84
  model.save!
76
85
  expect(req).to have_been_requested
77
86
  end
78
87
 
79
- it 'should still have unknown attribute' do
88
+ it 'stills have unknown attribute' do
80
89
  model.save!
81
90
  expect(model.attributes).to include 'born_at' => 'Berlin'
82
91
  end
83
92
 
84
- it 'should include server send unknown attribute' do
93
+ it 'includes server send unknown attribute' do
85
94
  model.save!
86
95
  expect(model.attributes).to include 'wuff' => 'woa'
87
96
  end
@@ -93,7 +102,7 @@ describe Acfs::Resource::Persistence do
93
102
  before { model.save! }
94
103
 
95
104
  it { expect(model).to be_persisted }
96
- it { expect(model).to_not be_new }
105
+ it { expect(model).not_to be_new }
97
106
  end
98
107
  end
99
108
 
@@ -101,46 +110,63 @@ describe Acfs::Resource::Persistence do
101
110
  let!(:model) { model_class.find 1 }
102
111
 
103
112
  describe '#update_attributes' do
104
- subject { -> { model.update_attributes name: 'John' } }
105
- it { expect { subject.call }.to raise_error Acfs::ResourceNotLoaded }
113
+ it 'to raise error' do
114
+ expect do
115
+ model.update_attributes({name: 'John'})
116
+ end.to raise_error Acfs::ResourceNotLoaded
117
+ end
106
118
  end
107
119
 
108
120
  describe '#update_attributes!' do
109
- subject { -> { model.update_attributes! name: 'John' } }
110
- it { expect { subject.call }.to raise_error Acfs::ResourceNotLoaded }
121
+ it 'to raise error' do
122
+ expect do
123
+ model.update_attributes!({name: 'John'})
124
+ end.to raise_error Acfs::ResourceNotLoaded
125
+ end
111
126
  end
112
127
  end
113
128
 
114
129
  context 'loaded model' do
115
130
  context 'without changes' do
116
131
  let(:model) { model_class.find 1 }
117
- before { model; Acfs.run }
132
+
133
+ before do
134
+ model
135
+ Acfs.run
136
+ end
118
137
 
119
138
  it { expect(model).to be_persisted }
120
- it { expect(model).to_not be_new }
139
+ it { expect(model).not_to be_new }
121
140
  end
122
141
 
123
142
  context 'with changes' do
124
143
  let(:model) { model_class.find 1 }
125
- before { model; Acfs.run; model.name = 'dhh' }
144
+
145
+ before do
146
+ model
147
+ Acfs.run
148
+ model.name = 'dhh'
149
+ end
126
150
 
127
151
  it { expect(model).to be_persisted }
128
- it { expect(model).to_not be_new }
152
+ it { expect(model).not_to be_new }
129
153
  end
130
154
 
131
155
  describe '#delete!' do
132
156
  let(:model) { model_class.find 1 }
133
- let(:before_acfs_run) {}
134
157
 
135
158
  describe 'normal delete actions' do
136
- before { model; Acfs.run }
159
+ before do
160
+ model
161
+ Acfs.run
162
+ end
137
163
 
138
- it 'should trigger DELETE request' do
164
+ it 'triggers DELETE request' do
139
165
  model.delete!
140
- expect(@del).to have_been_requested
166
+ expect(delete_stub).to have_been_requested
141
167
  end
142
168
 
143
- it 'should be frozen after DELETE' do
169
+ it 'is frozen after DELETE' do
144
170
  model.delete!
145
171
  expect(model.__getobj__).to be_frozen
146
172
  end
@@ -149,68 +175,80 @@ describe Acfs::Resource::Persistence do
149
175
  describe 'correct URL generation' do
150
176
  let(:model_class) { PathArguments }
151
177
  let(:model) { model_class.find 1, params: {required_arg: 'some_value'} }
178
+ let(:resource_url) { 'http://users.example.org/some_value/users/1' }
179
+
180
+ let!(:delete_stub) do
181
+ stub_request(:delete, resource_url)
182
+ .with(body: '{}')
183
+ .to_return response({id: 1, required_arg: 'some_value'}, {status: 200})
184
+ end
185
+
186
+ before do
187
+ stub_request(:get, resource_url)
188
+ .to_return response(id: 1, required_arg: 'some_value')
152
189
 
153
- before :each do
154
- resource_url = 'http://users.example.org/some_value/users/1'
155
- @my_get_stub = stub_request(:get, resource_url)
156
- .to_return response(id: 1, required_arg: 'some_value')
157
- @my_delete_stub = stub_request(:delete, resource_url)
158
- .with(body: '{}')
159
- .to_return response({id: 1, required_arg: 'some_value'}, {status: 200})
160
190
  model
161
191
  Acfs.run
162
192
  end
163
193
 
164
- it 'should not raise an error on URL generation' do
194
+ it 'does not raise an error on URL generation' do
165
195
  expect do
166
196
  model.delete!
167
197
  end.not_to raise_error
168
198
  end
169
199
 
170
- it 'should request the delete' do
200
+ it 'requests the delete' do
171
201
  model.delete!
172
- expect(@my_delete_stub).to have_been_requested
202
+ expect(delete_stub).to have_been_requested
173
203
  end
174
204
  end
175
205
  end
176
206
 
177
207
  describe '#update_atributes!' do
178
208
  let(:model) { model_class.find 1 }
179
- before { model; Acfs.run }
180
209
 
181
- it 'should set attributes' do
182
- model.update_attributes name: 'Idefix'
210
+ before do
211
+ model
212
+ Acfs.run
213
+ end
214
+
215
+ it 'sets attributes' do
216
+ model.update_attributes({name: 'Idefix'})
183
217
  expect(model.attributes.symbolize_keys).to eq id: 1, name: 'Idefix', age: 12
184
218
  end
185
219
 
186
- it 'should save resource' do
187
- expect(model.__getobj__).to receive(:save).with({})
188
- model.update_attributes name: 'Idefix'
220
+ it 'saves resource' do
221
+ expect(model.__getobj__).to receive(:save)
222
+ model.update_attributes({name: 'Idefix'})
189
223
  end
190
224
 
191
- it 'should pass second hash to save' do
225
+ it 'kwargses to save' do
192
226
  expect(model.__getobj__).to receive(:save).with(bla: 'blub')
193
- model.update_attributes({name: 'Idefix'}, {bla: 'blub'})
227
+ model.update_attributes({name: 'Idefix'}, bla: 'blub')
194
228
  end
195
229
  end
196
230
 
197
231
  describe '#update_atributes' do
198
232
  let(:model) { model_class.find 1 }
199
- before { model; Acfs.run }
200
233
 
201
- it 'should set attributes' do
202
- model.update_attributes! name: 'Idefix'
234
+ before do
235
+ model
236
+ Acfs.run
237
+ end
238
+
239
+ it 'sets attributes' do
240
+ model.update_attributes!({name: 'Idefix'})
203
241
  expect(model.attributes.symbolize_keys).to eq id: 1, name: 'Idefix', age: 12
204
242
  end
205
243
 
206
- it 'should save resource' do
207
- expect(model.__getobj__).to receive(:save!).with({})
208
- model.update_attributes! name: 'Idefix'
244
+ it 'saves resource' do
245
+ expect(model.__getobj__).to receive(:save!)
246
+ model.update_attributes!({name: 'Idefix'})
209
247
  end
210
248
 
211
- it 'should pass second hash to save' do
249
+ it 'passes second hash to save' do
212
250
  expect(model.__getobj__).to receive(:save!).with(bla: 'blub')
213
- model.update_attributes!({name: 'Idefix'}, {bla: 'blub'})
251
+ model.update_attributes!({name: 'Idefix'}, bla: 'blub')
214
252
  end
215
253
  end
216
254
  end
@@ -218,7 +256,11 @@ describe Acfs::Resource::Persistence do
218
256
  describe '.save!' do
219
257
  context 'with invalid data validated on server side' do
220
258
  let(:model) { model_class.find 1 }
221
- before { model; Acfs.run }
259
+
260
+ before do
261
+ model
262
+ Acfs.run
263
+ end
222
264
 
223
265
  before do
224
266
  stub_request(:put, 'http://users.example.org/users/1')
@@ -226,7 +268,7 @@ describe Acfs::Resource::Persistence do
226
268
  .to_return response({errors: {name: ['required']}}, {status: 422})
227
269
  end
228
270
 
229
- it 'should set local errors hash' do
271
+ it 'sets local errors hash' do
230
272
  model.name = ''
231
273
  begin
232
274
  model.save!
@@ -236,30 +278,19 @@ describe Acfs::Resource::Persistence do
236
278
  expect(model.errors.to_hash).to be == {name: %w[required]}
237
279
  end
238
280
  end
239
-
240
- context 'hash modification on iteration in ActiveModel when errors on field is nil' do
241
- let(:model) { model_class.find 1 }
242
- before { model; Acfs.run }
243
-
244
- before do
245
- stub_request(:put, 'http://users.example.org/users/1')
246
- .with(body: '{"id":1,"name":"","age":12}')
247
- .to_return response({errors: {name: ['required']}}, {status: 422})
248
- end
249
- end
250
281
  end
251
282
 
252
283
  describe '.create!' do
253
284
  context 'with valid data' do
254
285
  let(:data) { {name: 'Idefix', age: 12} }
255
286
 
256
- it 'should create new resource' do
287
+ it 'creates new resource' do
257
288
  model = model_class.create! data
258
289
  expect(model.name).to be == 'Idefix'
259
290
  expect(model.age).to be == 12
260
291
  end
261
292
 
262
- it 'should be persisted' do
293
+ it 'is persisted' do
263
294
  model = model_class.create! data
264
295
  expect(model).to be_persisted
265
296
  end
@@ -268,7 +299,7 @@ describe Acfs::Resource::Persistence do
268
299
  context 'with invalid data' do
269
300
  let(:data) { {name: nil, age: 12} }
270
301
 
271
- it 'should raise an error' do
302
+ it 'raises an error' do
272
303
  expect { model_class.create! data }.to \
273
304
  raise_error(::Acfs::InvalidResource) do |error|
274
305
  expect(error.errors).to be == {'name' => %w[required]}
@@ -278,44 +309,45 @@ describe Acfs::Resource::Persistence do
278
309
  end
279
310
 
280
311
  describe '.create' do
281
- subject { model_class.create data }
312
+ subject(:model) { model_class.create data }
282
313
 
283
314
  context 'with valid data' do
284
315
  let(:data) { {name: 'Idefix', age: 12} }
285
316
 
286
- it 'should create new resource' do
287
- expect(subject.name).to be == 'Idefix'
288
- expect(subject.age).to be == 12
317
+ it 'creates new resource' do
318
+ expect(model.name).to be == 'Idefix'
319
+ expect(model.age).to be == 12
289
320
  end
290
321
 
291
- it 'should be persisted' do
292
- expect(subject).to be_persisted
322
+ it 'is persisted' do
323
+ expect(model).to be_persisted
293
324
  end
294
325
  end
295
326
 
296
327
  context 'with invalid data' do
297
328
  let(:data) { {name: nil, age: 12} }
298
329
 
299
- it 'should return not persisted resource' do
300
- expect(subject).to_not be_persisted
330
+ it 'returns not persisted resource' do
331
+ expect(model).not_to be_persisted
301
332
  end
302
333
 
303
- it 'should contain error hash' do
304
- expect(subject.errors.to_hash).to eq name: %w[required]
334
+ it 'contains error hash' do
335
+ expect(model.errors.to_hash).to eq name: %w[required]
305
336
  end
306
337
  end
307
338
 
308
339
  context 'with additional data' do
309
- let!(:req) do
340
+ before do
310
341
  stub_request(:post, 'http://users.example.org/users')
311
342
  .with(body: '{"id":null,"name":"Anon","age":9,"born_at":"today"}')
312
343
  .to_return response(id: 5, name: 'Anon', age: 9)
313
344
  end
345
+
314
346
  let(:data) { {age: 9, born_at: 'today'} }
315
347
 
316
- it 'should store them in attributes' do
317
- expect(subject.attributes).to eq 'id' => 5, 'name' => 'Anon',
318
- 'age' => 9, 'born_at' => 'today'
348
+ it 'stores them in attributes' do
349
+ expect(model.attributes).to eq 'id' => 5, 'name' => 'Anon',
350
+ 'age' => 9, 'born_at' => 'today'
319
351
  end
320
352
  end
321
353
  end