acfs 0.32.1.1.b275 → 0.32.1.1.b276
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.
- 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
|