acfs 0.32.1.1.b275 → 0.32.1.1.b276
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +1 -0
- data/lib/acfs/model.rb +3 -3
- data/lib/acfs/model/attributes.rb +31 -15
- data/lib/acfs/model/initialization.rb +1 -3
- data/lib/acfs/model/persistence.rb +4 -4
- data/lib/acfs/stub.rb +7 -1
- data/spec/acfs/model/attributes_spec.rb +9 -20
- data/spec/acfs/model/initialization_spec.rb +1 -1
- data/spec/acfs/model/persistance_spec.rb +54 -17
- data/spec/acfs/model/query_methods_spec.rb +4 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YmRiYmQxMWZhODVlMWQxMjIwYTY3NDhkMjlkM2NjNjQ2YjA0NjIwMQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MmQ5YzdiNjJhYmM0Y2NjZDM2OWRhMzZlMjhiY2JjODM0MzY4YjdkZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Yzk4YTk4ZGU2NGY0ZGZhNTk4YzY4MzIzZmUyMTkyODY3ZjdlNDFhMGRlNzc4
|
10
|
+
OTA1NDc4YjU3MGUwOTMwNzNmMWUyOGIyZGNiMjVlNDExMGRhZDE4NTA4NDVm
|
11
|
+
NDY0NDhkZTE1MTgyYzllMjlkMGRkODMzMGQ1Njg5N2RlYWFhYjE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YjY1YjYzZjU1YjZhNGQwZGFmYTNkNDgyZWI2NTNjMzE0NWU3ZTIzOTA3Yjky
|
14
|
+
MDdhNTQ4MGZhMTJjZjgzZmRjZWQ2N2M3ZDQzMTQ0NWZkYWJiMzZjNzYzNjY4
|
15
|
+
ZThkMzAzY2U0ZWM2MDM3M2FhZWQ5NTgzMmQyOTNjYThjOWUxMmU=
|
data/CHANGELOG.md
CHANGED
data/lib/acfs/model.rb
CHANGED
@@ -3,6 +3,7 @@ require 'active_model'
|
|
3
3
|
# @api public
|
4
4
|
#
|
5
5
|
module Acfs::Model
|
6
|
+
require 'acfs/model/initialization'
|
6
7
|
require 'acfs/model/attributes'
|
7
8
|
require 'acfs/model/dirty'
|
8
9
|
require 'acfs/model/loadable'
|
@@ -24,11 +25,10 @@ module Acfs::Model
|
|
24
25
|
extend ActiveModel::Translation
|
25
26
|
include ActiveModel::Conversion
|
26
27
|
include ActiveModel::Validations
|
27
|
-
|
28
|
-
require 'acfs/model/initialization'
|
29
|
-
include Initialization
|
30
28
|
end
|
31
29
|
|
30
|
+
include Initialization
|
31
|
+
|
32
32
|
include Attributes
|
33
33
|
include Loadable
|
34
34
|
include Persistence
|
@@ -27,7 +27,8 @@ module Acfs::Model
|
|
27
27
|
# @see ClassMethods#attributes
|
28
28
|
#
|
29
29
|
def initialize(*attrs)
|
30
|
-
self.write_attributes self.class.attributes
|
30
|
+
self.write_attributes self.class.attributes
|
31
|
+
reset_changes
|
31
32
|
super
|
32
33
|
end
|
33
34
|
|
@@ -46,7 +47,7 @@ module Acfs::Model
|
|
46
47
|
# @return [ HashWithIndifferentAccess{ Symbol => Object } ] Attributes and their values.
|
47
48
|
#
|
48
49
|
def attributes
|
49
|
-
|
50
|
+
@attributes ||= HashWithIndifferentAccess.new
|
50
51
|
end
|
51
52
|
|
52
53
|
# @api public
|
@@ -73,7 +74,7 @@ module Acfs::Model
|
|
73
74
|
# @return [ Object ] Attribute value.
|
74
75
|
#
|
75
76
|
def read_attribute(name)
|
76
|
-
|
77
|
+
self.attributes[name.to_s]
|
77
78
|
end
|
78
79
|
|
79
80
|
# @api public
|
@@ -96,7 +97,9 @@ module Acfs::Model
|
|
96
97
|
# @see #write_attribute Delegates attribute values to `#write_attribute`.
|
97
98
|
#
|
98
99
|
def write_attributes(attributes, opts = {})
|
99
|
-
|
100
|
+
unless attributes.respond_to?(:each) && attributes.respond_to?(:keys)
|
101
|
+
return false
|
102
|
+
end
|
100
103
|
|
101
104
|
if opts.fetch(:unknown,:ignore) == :raise
|
102
105
|
if (attributes.keys.map(&:to_s) - self.class.attributes.keys).any?
|
@@ -104,27 +107,39 @@ module Acfs::Model
|
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
107
|
-
attributes = attributes.select do |k, v|
|
108
|
-
self.class.attributes.keys.include? k.to_s
|
109
|
-
end
|
110
|
-
|
111
110
|
procs = {}
|
112
111
|
|
113
112
|
attributes.each do |key, _|
|
114
113
|
if attributes[key].is_a? Proc
|
115
114
|
procs[key] = attributes[key]
|
116
115
|
else
|
117
|
-
|
116
|
+
write_local_attribute key, attributes[key], opts
|
118
117
|
end
|
119
118
|
end
|
120
119
|
|
121
120
|
procs.each do |key, proc|
|
122
|
-
|
121
|
+
write_local_attribute key, instance_exec(&proc), opts
|
123
122
|
end
|
124
123
|
|
125
124
|
true
|
126
125
|
end
|
127
126
|
|
127
|
+
# @api private
|
128
|
+
#
|
129
|
+
# Check if a public getter for attribute exists that should be called to
|
130
|
+
# write it or of {#write_attribute} should be called directly. This is
|
131
|
+
# necessary as {#write_attribute} should go though setters but can also
|
132
|
+
# handle unknown attribute that will not have a generated setter method.
|
133
|
+
#
|
134
|
+
def write_local_attribute(name, value, opts = {})
|
135
|
+
method = "#{name}="
|
136
|
+
if respond_to? method, true
|
137
|
+
public_send method, value
|
138
|
+
else
|
139
|
+
write_attribute name, value, opts
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
128
143
|
# @api public
|
129
144
|
#
|
130
145
|
# Write single attribute with given value. Value will be casted
|
@@ -135,11 +150,12 @@ module Acfs::Model
|
|
135
150
|
# @raise [ ArgumentError ] If no attribute with given name is defined.
|
136
151
|
#
|
137
152
|
def write_attribute(name, value, opts = {})
|
138
|
-
|
139
|
-
|
153
|
+
attr_type = self.class.defined_attributes[name.to_s]
|
154
|
+
if attr_type
|
155
|
+
write_raw_attribute name, attr_type.cast(value), opts
|
156
|
+
else
|
157
|
+
write_raw_attribute name, value, opts
|
140
158
|
end
|
141
|
-
|
142
|
-
write_raw_attribute name, attr.cast(value), opts
|
143
159
|
end
|
144
160
|
|
145
161
|
# @api private
|
@@ -152,7 +168,7 @@ module Acfs::Model
|
|
152
168
|
# @param [ Object ] value Attribute value.
|
153
169
|
#
|
154
170
|
def write_raw_attribute(name, value, _ = {})
|
155
|
-
|
171
|
+
self.attributes[name.to_s] = value
|
156
172
|
end
|
157
173
|
|
158
174
|
module ClassMethods
|
@@ -24,9 +24,7 @@ module Acfs::Model
|
|
24
24
|
# @param [ Hash{ Symbol => Object } ] params Attributes to set on resource.
|
25
25
|
#
|
26
26
|
def initialize(params = {})
|
27
|
-
|
28
|
-
self.public_send("#{attr}=", value)
|
29
|
-
end if params
|
27
|
+
self.write_attributes params if params
|
30
28
|
end
|
31
29
|
|
32
30
|
end
|
@@ -195,8 +195,8 @@ module Acfs
|
|
195
195
|
# @see #create
|
196
196
|
#
|
197
197
|
def create!(data, opts = {})
|
198
|
-
new.tap do |model|
|
199
|
-
model.save!
|
198
|
+
new(data).tap do |model|
|
199
|
+
model.save!
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
@@ -218,8 +218,8 @@ module Acfs
|
|
218
218
|
# @see #create!
|
219
219
|
#
|
220
220
|
def create(data, opts = {})
|
221
|
-
model = new
|
222
|
-
model.save
|
221
|
+
model = new data
|
222
|
+
model.save
|
223
223
|
model
|
224
224
|
end
|
225
225
|
end
|
data/lib/acfs/stub.rb
CHANGED
@@ -23,7 +23,13 @@ module Acfs
|
|
23
23
|
params = op.full_params.stringify_keys
|
24
24
|
data = op.data.stringify_keys
|
25
25
|
|
26
|
-
opts[:with] == params || data == opts[:with]
|
26
|
+
return true if opts[:with] == params || data == opts[:with]
|
27
|
+
return true if (opts[:with].nil? && params.empty? && data.empty?)
|
28
|
+
|
29
|
+
return true if opts[:with].reject{|k,v|v.nil?} == params.reject{|k,v|v.nil?}
|
30
|
+
return true if opts[:with].reject{|k,v|v.nil?} == data.reject{|k,v|v.nil?}
|
31
|
+
|
32
|
+
false
|
27
33
|
end
|
28
34
|
|
29
35
|
def calls
|
@@ -41,6 +41,9 @@ describe Acfs::Model::Attributes do
|
|
41
41
|
before do
|
42
42
|
model.attribute :name, :string, default: 'John'
|
43
43
|
model.attribute :age, :integer, default: 25
|
44
|
+
model.send :define_method, :name= do |name|
|
45
|
+
write_attribute :name, "The Great #{name}"
|
46
|
+
end
|
44
47
|
end
|
45
48
|
let(:args) { [params] }
|
46
49
|
let(:params){ {name: 'James'} }
|
@@ -50,8 +53,8 @@ describe Acfs::Model::Attributes do
|
|
50
53
|
|
51
54
|
it 'should update attributes' do
|
52
55
|
should change(m, :attributes)
|
53
|
-
.from({'name' => 'John', 'age' => 25})
|
54
|
-
.to({'name' => 'James', 'age' => 25})
|
56
|
+
.from({'name' => 'The Great John', 'age' => 25})
|
57
|
+
.to({'name' => 'The Great James', 'age' => 25})
|
55
58
|
end
|
56
59
|
|
57
60
|
context 'without non-hash params' do
|
@@ -62,14 +65,14 @@ describe Acfs::Model::Attributes do
|
|
62
65
|
end
|
63
66
|
|
64
67
|
context 'with unknown attributes' do
|
65
|
-
let(:params) { {name: 'James', born_at:
|
68
|
+
let(:params) { {name: 'James', born_at: 'today'} }
|
66
69
|
|
67
70
|
it { should_not raise_error }
|
68
71
|
|
69
|
-
it 'should update known attributes' do
|
72
|
+
it 'should update known attributes and store unknown' do
|
70
73
|
should change(m, :attributes)
|
71
|
-
.from({'name' => 'John', 'age' => 25})
|
72
|
-
.to({'name' => 'James', 'age' => 25})
|
74
|
+
.from({'name' => 'The Great John', 'age' => 25})
|
75
|
+
.to({'name' => 'The Great James', 'age' => 25, 'born_at' => 'today'})
|
73
76
|
end
|
74
77
|
|
75
78
|
context 'with unknown: :raise option' do
|
@@ -94,13 +97,6 @@ describe Acfs::Model::Attributes do
|
|
94
97
|
it 'should return default value' do
|
95
98
|
expect(model.new.name).to be == 'John'
|
96
99
|
end
|
97
|
-
|
98
|
-
it 'should return matching ivar\'s value' do
|
99
|
-
o = model.new
|
100
|
-
o.instance_variable_set :@name, 'Johannes'
|
101
|
-
|
102
|
-
expect(o.name).to be == 'Johannes'
|
103
|
-
end
|
104
100
|
end
|
105
101
|
|
106
102
|
describe '#_setter_' do
|
@@ -116,13 +112,6 @@ describe Acfs::Model::Attributes do
|
|
116
112
|
expect(o.name).to be == 'Paul'
|
117
113
|
end
|
118
114
|
|
119
|
-
it 'should set instance var' do
|
120
|
-
o = model.new
|
121
|
-
o.name = 'Paul'
|
122
|
-
|
123
|
-
expect(o.instance_variable_get(:@name)).to be == 'Paul'
|
124
|
-
end
|
125
|
-
|
126
115
|
it 'should update attributes hash' do
|
127
116
|
o = model.new
|
128
117
|
o.name = 'Johannes'
|
@@ -18,11 +18,11 @@ describe Acfs::Model::Persistence do
|
|
18
18
|
.to_return response({ id: 5, name: 'Anon', age: 12 })
|
19
19
|
|
20
20
|
stub_request(:post, 'http://users.example.org/users')
|
21
|
-
.with(body: '{"name":"Idefix","age":12}')
|
21
|
+
.with(body: '{id:null,"name":"Idefix","age":12}')
|
22
22
|
.to_return response({ id: 5, name: 'Idefix', age: 12 })
|
23
23
|
|
24
24
|
stub_request(:post, 'http://users.example.org/users')
|
25
|
-
.with(body: '{"age":12}')
|
25
|
+
.with(body: '{"id":null,"name":null,"age":12}')
|
26
26
|
.to_return response({ errors: { name: [ 'required' ] }}, status: 422)
|
27
27
|
|
28
28
|
@del = stub_request(:delete, 'http://users.example.org/users/1')
|
@@ -60,6 +60,30 @@ describe Acfs::Model::Persistence do
|
|
60
60
|
|
61
61
|
expect(@post_stub).to have_been_requested
|
62
62
|
end
|
63
|
+
|
64
|
+
context 'with unknown attributes' do
|
65
|
+
let!(:req) do
|
66
|
+
stub_request(:post, 'http://users.example.org/users')
|
67
|
+
.with(body: '{"id":null,"name":"Idefix","age":null,"born_at":"Berlin"}')
|
68
|
+
.to_return response({id: 5, name: 'Idefix', age: 12, wuff: 'woa'})
|
69
|
+
end
|
70
|
+
let(:model) { model_class.new name: 'Idefix', born_at: 'Berlin' }
|
71
|
+
|
72
|
+
it 'should POST to collection URL' do
|
73
|
+
model.save!
|
74
|
+
expect(req).to have_been_requested
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should still have unknown attribute' do
|
78
|
+
model.save!
|
79
|
+
expect(model.attributes).to include 'born_at' => 'Berlin'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should include server send unknown attribute' do
|
83
|
+
model.save!
|
84
|
+
expect(model.attributes).to include 'wuff' => 'woa'
|
85
|
+
end
|
86
|
+
end
|
63
87
|
end
|
64
88
|
end
|
65
89
|
|
@@ -205,43 +229,56 @@ describe Acfs::Model::Persistence do
|
|
205
229
|
end
|
206
230
|
|
207
231
|
context 'with invalid data' do
|
208
|
-
let(:data) { { age: 12
|
232
|
+
let(:data) { {name: nil, age: 12} }
|
209
233
|
|
210
234
|
it 'should raise an error' do
|
211
|
-
expect
|
212
|
-
|
213
|
-
|
235
|
+
expect{ model_class.create! data }.to \
|
236
|
+
raise_error(::Acfs::InvalidResource) do |error|
|
237
|
+
expect(error.errors).to be == { 'name' => %w(required) }
|
238
|
+
end
|
214
239
|
end
|
215
240
|
end
|
216
241
|
end
|
217
242
|
|
218
243
|
describe '.create' do
|
244
|
+
subject { model_class.create data }
|
245
|
+
|
219
246
|
context 'with valid data' do
|
220
|
-
let(:data) { {
|
247
|
+
let(:data) { {name: 'Idefix', age: 12} }
|
221
248
|
|
222
249
|
it 'should create new resource' do
|
223
|
-
|
224
|
-
expect(
|
225
|
-
expect(model.age).to be == 12
|
250
|
+
expect(subject.name).to be == 'Idefix'
|
251
|
+
expect(subject.age).to be == 12
|
226
252
|
end
|
227
253
|
|
228
254
|
it 'should be persisted' do
|
229
|
-
|
230
|
-
expect(model).to be_persisted
|
255
|
+
expect(subject).to be_persisted
|
231
256
|
end
|
232
257
|
end
|
233
258
|
|
234
259
|
context 'with invalid data' do
|
235
|
-
let(:data) { { age: 12
|
260
|
+
let(:data) { {name: nil, age: 12} }
|
236
261
|
|
237
262
|
it 'should return not persisted resource' do
|
238
|
-
|
239
|
-
expect(model).to_not be_persisted
|
263
|
+
expect(subject).to_not be_persisted
|
240
264
|
end
|
241
265
|
|
242
266
|
it 'should contain error hash' do
|
243
|
-
|
244
|
-
|
267
|
+
expect(subject.errors.to_hash).to eq name: %w(required)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'with additional data' do
|
272
|
+
let!(:req) do
|
273
|
+
stub_request(:post, 'http://users.example.org/users')
|
274
|
+
.with(body: '{"id":null,"name":"Anon","age":9,"born_at":"today"}')
|
275
|
+
.to_return response({id: 5, name: 'Anon', age: 9})
|
276
|
+
end
|
277
|
+
let(:data) { {age: 9, born_at: 'today'} }
|
278
|
+
|
279
|
+
it 'should store them in attributes' do
|
280
|
+
expect(subject.attributes).to eq 'id' => 5, 'name' => 'Anon',
|
281
|
+
'age' => 9, 'born_at' => 'today'
|
245
282
|
end
|
246
283
|
end
|
247
284
|
end
|
@@ -7,15 +7,16 @@ describe Acfs::Model::QueryMethods do
|
|
7
7
|
context 'with single id' do
|
8
8
|
context 'with successful response' do
|
9
9
|
before do
|
10
|
-
stub_request(:get, 'http://users.example.org/users/1').to_return response({
|
11
|
-
stub_request(:get, 'http://users.example.org/users/2').to_return response({
|
10
|
+
stub_request(:get, 'http://users.example.org/users/1').to_return response({id: 1, name: 'Anon', age: 12, born_at: 'Berlin'})
|
11
|
+
stub_request(:get, 'http://users.example.org/users/2').to_return response({id: 2, type: 'Customer', name: 'Clare Customer', age: 24 })
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'should load a single remote resource' do
|
15
15
|
user = model.find 1
|
16
16
|
Acfs.run
|
17
17
|
|
18
|
-
expect(user.attributes).to
|
18
|
+
expect(user.attributes).to eq(
|
19
|
+
{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}.stringify_keys)
|
19
20
|
end
|
20
21
|
|
21
22
|
it 'should invoke callback after model is loaded' do
|