active_data 1.0.0 → 1.1.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.
- checksums.yaml +5 -5
- data/.codeclimate.yml +13 -0
- data/.rubocop.yml +56 -0
- data/.rubocop_todo.yml +53 -0
- data/.rvmrc +1 -1
- data/.travis.yml +15 -2
- data/Appraisals +1 -1
- data/CHANGELOG.md +31 -0
- data/Guardfile +8 -8
- data/README.md +256 -0
- data/Rakefile +2 -4
- data/active_data.gemspec +8 -7
- data/gemfiles/rails.4.0.gemfile +1 -1
- data/gemfiles/rails.4.1.gemfile +1 -1
- data/gemfiles/rails.4.2.gemfile +1 -1
- data/gemfiles/rails.5.0.gemfile +1 -1
- data/gemfiles/rails.5.1.gemfile +14 -0
- data/lib/active_data/active_record/associations.rb +18 -13
- data/lib/active_data/active_record/nested_attributes.rb +8 -14
- data/lib/active_data/base.rb +13 -0
- data/lib/active_data/config.rb +4 -4
- data/lib/active_data/errors.rb +29 -13
- data/lib/active_data/extensions.rb +22 -21
- data/lib/active_data/model/associations/base.rb +22 -6
- data/lib/active_data/model/associations/embeds_any.rb +17 -0
- data/lib/active_data/model/associations/embeds_many.rb +29 -19
- data/lib/active_data/model/associations/embeds_one.rb +30 -26
- data/lib/active_data/model/associations/nested_attributes.rb +82 -50
- data/lib/active_data/model/associations/persistence_adapters/active_record/referenced_proxy.rb +31 -0
- data/lib/active_data/model/associations/persistence_adapters/active_record.rb +66 -0
- data/lib/active_data/model/associations/persistence_adapters/base.rb +53 -0
- data/lib/active_data/model/associations/references_any.rb +41 -0
- data/lib/active_data/model/associations/references_many.rb +51 -37
- data/lib/active_data/model/associations/references_one.rb +43 -41
- data/lib/active_data/model/associations/reflections/base.rb +19 -29
- data/lib/active_data/model/associations/reflections/embeds_any.rb +43 -0
- data/lib/active_data/model/associations/reflections/embeds_many.rb +3 -13
- data/lib/active_data/model/associations/reflections/embeds_one.rb +5 -37
- data/lib/active_data/model/associations/reflections/references_any.rb +62 -0
- data/lib/active_data/model/associations/reflections/references_many.rb +7 -7
- data/lib/active_data/model/associations/reflections/references_one.rb +9 -7
- data/lib/active_data/model/associations/reflections/singular.rb +35 -0
- data/lib/active_data/model/associations/validations.rb +2 -27
- data/lib/active_data/model/associations.rb +12 -10
- data/lib/active_data/model/attributes/attribute.rb +10 -10
- data/lib/active_data/model/attributes/base.rb +8 -7
- data/lib/active_data/model/attributes/localized.rb +4 -4
- data/lib/active_data/model/attributes/reference_many.rb +6 -8
- data/lib/active_data/model/attributes/reference_one.rb +17 -9
- data/lib/active_data/model/attributes/reflections/attribute.rb +2 -2
- data/lib/active_data/model/attributes/reflections/base.rb +8 -11
- data/lib/active_data/model/attributes/reflections/localized.rb +2 -2
- data/lib/active_data/model/attributes/reflections/reference_one.rb +11 -22
- data/lib/active_data/model/attributes/reflections/represents.rb +5 -6
- data/lib/active_data/model/attributes/represents.rb +6 -5
- data/lib/active_data/model/attributes.rb +33 -87
- data/lib/active_data/model/callbacks.rb +6 -7
- data/lib/active_data/model/conventions.rb +2 -0
- data/lib/active_data/model/dirty.rb +4 -4
- data/lib/active_data/model/lifecycle.rb +18 -20
- data/lib/active_data/model/localization.rb +5 -2
- data/lib/active_data/model/persistence.rb +2 -2
- data/lib/active_data/model/primary.rb +19 -14
- data/lib/active_data/model/representation.rb +81 -0
- data/lib/active_data/model/scopes.rb +22 -12
- data/lib/active_data/model/validations/associated.rb +3 -2
- data/lib/active_data/model/validations/nested.rb +6 -1
- data/lib/active_data/model/validations.rb +3 -3
- data/lib/active_data/model.rb +2 -1
- data/lib/active_data/undefined_class.rb +9 -0
- data/lib/active_data/version.rb +1 -1
- data/lib/active_data.rb +40 -17
- data/spec/lib/active_data/active_record/associations_spec.rb +107 -45
- data/spec/lib/active_data/active_record/nested_attributes_spec.rb +1 -2
- data/spec/lib/active_data/config_spec.rb +37 -15
- data/spec/lib/active_data/model/associations/embeds_many_spec.rb +475 -172
- data/spec/lib/active_data/model/associations/embeds_one_spec.rb +353 -96
- data/spec/lib/active_data/model/associations/nested_attributes_spec.rb +108 -12
- data/spec/lib/active_data/model/associations/persistence_adapters/active_record_spec.rb +58 -0
- data/spec/lib/active_data/model/associations/references_many_spec.rb +440 -64
- data/spec/lib/active_data/model/associations/references_one_spec.rb +347 -36
- data/spec/lib/active_data/model/associations/reflections/embeds_many_spec.rb +8 -7
- data/spec/lib/active_data/model/associations/reflections/embeds_one_spec.rb +7 -6
- data/spec/lib/active_data/model/associations/reflections/references_many_spec.rb +81 -33
- data/spec/lib/active_data/model/associations/reflections/references_one_spec.rb +116 -37
- data/spec/lib/active_data/model/associations/validations_spec.rb +27 -43
- data/spec/lib/active_data/model/associations_spec.rb +34 -25
- data/spec/lib/active_data/model/attributes/attribute_spec.rb +26 -23
- data/spec/lib/active_data/model/attributes/base_spec.rb +5 -6
- data/spec/lib/active_data/model/attributes/collection_spec.rb +7 -8
- data/spec/lib/active_data/model/attributes/dictionary_spec.rb +40 -33
- data/spec/lib/active_data/model/attributes/localized_spec.rb +27 -28
- data/spec/lib/active_data/model/attributes/reflections/attribute_spec.rb +6 -6
- data/spec/lib/active_data/model/attributes/represents_spec.rb +10 -78
- data/spec/lib/active_data/model/attributes_spec.rb +150 -45
- data/spec/lib/active_data/model/callbacks_spec.rb +69 -70
- data/spec/lib/active_data/model/conventions_spec.rb +0 -1
- data/spec/lib/active_data/model/dirty_spec.rb +22 -13
- data/spec/lib/active_data/model/lifecycle_spec.rb +49 -23
- data/spec/lib/active_data/model/persistence_spec.rb +5 -6
- data/spec/lib/active_data/model/representation_spec.rb +126 -0
- data/spec/lib/active_data/model/scopes_spec.rb +1 -3
- data/spec/lib/active_data/model/typecasting_spec.rb +6 -5
- data/spec/lib/active_data/model/validations/associated_spec.rb +26 -18
- data/spec/lib/active_data/model/validations/nested_spec.rb +89 -18
- data/spec/lib/active_data/model_spec.rb +1 -2
- data/spec/lib/active_data_spec.rb +0 -1
- data/spec/shared/nested_attribute_examples.rb +332 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/model_helpers.rb +2 -2
- data/spec/support/muffle_helper.rb +7 -0
- metadata +52 -18
- data/lib/active_data/model/associations/collection/referenced.rb +0 -26
- data/lib/active_data/model/associations/reflections/reference_reflection.rb +0 -45
- data/spec/lib/active_data/model/nested_attributes.rb +0 -202
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
describe ActiveData::Model::Lifecycle do
|
|
@@ -11,7 +10,7 @@ describe ActiveData::Model::Lifecycle do
|
|
|
11
10
|
|
|
12
11
|
subject { User.new }
|
|
13
12
|
|
|
14
|
-
[
|
|
13
|
+
%i[save create update destroy].each do |action|
|
|
15
14
|
specify { expect { subject.public_send "_#{action}_performer=", '' }.to raise_error NoMethodError }
|
|
16
15
|
end
|
|
17
16
|
|
|
@@ -19,9 +18,9 @@ describe ActiveData::Model::Lifecycle do
|
|
|
19
18
|
let(:foo) { true }
|
|
20
19
|
|
|
21
20
|
specify { expect { subject.save { foo } }.to raise_error NameError }
|
|
22
|
-
specify { expect { subject.save { |
|
|
21
|
+
specify { expect { subject.save { |_| attributes } }.to raise_error NameError }
|
|
23
22
|
specify { expect(subject.save { attributes }).to eq(true) }
|
|
24
|
-
specify { expect(subject.save { |
|
|
23
|
+
specify { expect(subject.save { |_| foo }).to eq(true) }
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
context 'save' do
|
|
@@ -87,7 +86,7 @@ describe ActiveData::Model::Lifecycle do
|
|
|
87
86
|
|
|
88
87
|
attribute :actions, Array, default: []
|
|
89
88
|
|
|
90
|
-
def append
|
|
89
|
+
def append(action)
|
|
91
90
|
self.actions = actions + [action]
|
|
92
91
|
end
|
|
93
92
|
|
|
@@ -106,7 +105,7 @@ describe ActiveData::Model::Lifecycle do
|
|
|
106
105
|
subject.destroy
|
|
107
106
|
subject.destroy
|
|
108
107
|
subject.save
|
|
109
|
-
expect(subject.actions).to eq([
|
|
108
|
+
expect(subject.actions).to eq(%i[destroy create update destroy destroy create])
|
|
110
109
|
end
|
|
111
110
|
end
|
|
112
111
|
end
|
|
@@ -198,10 +197,14 @@ describe ActiveData::Model::Lifecycle do
|
|
|
198
197
|
specify { expect { subject.update({}) }.not_to change { subject.persisted? } }
|
|
199
198
|
specify { expect { subject.update!({}) }.to raise_error ActiveData::ValidationError }
|
|
200
199
|
|
|
201
|
-
specify
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
specify do
|
|
201
|
+
expect { subject.update(name: 'Jonny') }
|
|
202
|
+
.to change { Storage.storage.keys }.from([]).to([subject.id])
|
|
203
|
+
end
|
|
204
|
+
specify do
|
|
205
|
+
expect { subject.update!(name: 'Jonny') }
|
|
206
|
+
.to change { Storage.storage.keys }.from([]).to([subject.id])
|
|
207
|
+
end
|
|
205
208
|
end
|
|
206
209
|
|
|
207
210
|
describe '#update_attributes, #update_attributes!' do
|
|
@@ -213,10 +216,14 @@ describe ActiveData::Model::Lifecycle do
|
|
|
213
216
|
specify { expect { subject.update_attributes({}) }.not_to change { subject.persisted? } }
|
|
214
217
|
specify { expect { subject.update_attributes!({}) }.to raise_error ActiveData::ValidationError }
|
|
215
218
|
|
|
216
|
-
specify
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
219
|
+
specify do
|
|
220
|
+
expect { subject.update_attributes(name: 'Jonny') }
|
|
221
|
+
.to change { Storage.storage.keys }.from([]).to([subject.id])
|
|
222
|
+
end
|
|
223
|
+
specify do
|
|
224
|
+
expect { subject.update_attributes!(name: 'Jonny') }
|
|
225
|
+
.to change { Storage.storage.keys }.from([]).to([subject.id])
|
|
226
|
+
end
|
|
220
227
|
end
|
|
221
228
|
|
|
222
229
|
describe '#save, #save!' do
|
|
@@ -230,7 +237,10 @@ describe ActiveData::Model::Lifecycle do
|
|
|
230
237
|
specify { expect { subject.save! }.to raise_error ActiveData::ValidationError }
|
|
231
238
|
|
|
232
239
|
specify { expect { subject.save }.not_to change { subject.persisted? } }
|
|
233
|
-
specify
|
|
240
|
+
specify do
|
|
241
|
+
expect { muffle(ActiveData::ValidationError) { subject.save! } }
|
|
242
|
+
.not_to change { subject.persisted? }
|
|
243
|
+
end
|
|
234
244
|
end
|
|
235
245
|
|
|
236
246
|
context 'create' do
|
|
@@ -257,7 +267,10 @@ describe ActiveData::Model::Lifecycle do
|
|
|
257
267
|
specify { expect { subject.save! }.to raise_error ActiveData::ObjectNotSaved }
|
|
258
268
|
|
|
259
269
|
specify { expect { subject.save }.not_to change { subject.persisted? } }
|
|
260
|
-
specify
|
|
270
|
+
specify do
|
|
271
|
+
expect { muffle(ActiveData::ObjectNotSaved) { subject.save! } }
|
|
272
|
+
.not_to change { subject.persisted? }
|
|
273
|
+
end
|
|
261
274
|
end
|
|
262
275
|
end
|
|
263
276
|
|
|
@@ -273,10 +286,14 @@ describe ActiveData::Model::Lifecycle do
|
|
|
273
286
|
specify { expect { subject.save }.not_to change { subject.persisted? } }
|
|
274
287
|
specify { expect { subject.save! }.not_to change { subject.persisted? } }
|
|
275
288
|
|
|
276
|
-
specify
|
|
277
|
-
.
|
|
278
|
-
|
|
279
|
-
|
|
289
|
+
specify do
|
|
290
|
+
expect { subject.save }.to change { Storage.storage[subject.id] }
|
|
291
|
+
.from(hash_including(name: 'Jonny')).to(hash_including(name: 'Jimmy'))
|
|
292
|
+
end
|
|
293
|
+
specify do
|
|
294
|
+
expect { subject.save! }.to change { Storage.storage[subject.id] }
|
|
295
|
+
.from(hash_including(name: 'Jonny')).to(hash_including(name: 'Jimmy'))
|
|
296
|
+
end
|
|
280
297
|
|
|
281
298
|
context 'save failed' do
|
|
282
299
|
before { User.define_save { false } }
|
|
@@ -287,7 +304,10 @@ describe ActiveData::Model::Lifecycle do
|
|
|
287
304
|
specify { expect { subject.save! }.to raise_error ActiveData::ObjectNotSaved }
|
|
288
305
|
|
|
289
306
|
specify { expect { subject.save }.not_to change { subject.persisted? } }
|
|
290
|
-
specify
|
|
307
|
+
specify do
|
|
308
|
+
expect { muffle(ActiveData::ObjectNotSaved) { subject.save! } }
|
|
309
|
+
.not_to change { subject.persisted? }
|
|
310
|
+
end
|
|
291
311
|
end
|
|
292
312
|
end
|
|
293
313
|
end
|
|
@@ -320,10 +340,16 @@ describe ActiveData::Model::Lifecycle do
|
|
|
320
340
|
specify { expect { subject.destroy! }.to raise_error ActiveData::ObjectNotDestroyed }
|
|
321
341
|
|
|
322
342
|
specify { expect { subject.destroy }.not_to change { subject.persisted? } }
|
|
323
|
-
specify
|
|
343
|
+
specify do
|
|
344
|
+
expect { muffle(ActiveData::ObjectNotDestroyed) { subject.destroy! } }
|
|
345
|
+
.not_to change { subject.persisted? }
|
|
346
|
+
end
|
|
324
347
|
|
|
325
348
|
specify { expect { subject.destroy }.not_to change { subject.destroyed? } }
|
|
326
|
-
specify
|
|
349
|
+
specify do
|
|
350
|
+
expect { muffle(ActiveData::ObjectNotDestroyed) { subject.destroy! } }
|
|
351
|
+
.not_to change { subject.destroyed? }
|
|
352
|
+
end
|
|
327
353
|
end
|
|
328
354
|
end
|
|
329
355
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
describe ActiveData::Model::Persistence do
|
|
@@ -22,7 +21,7 @@ describe ActiveData::Model::Persistence do
|
|
|
22
21
|
context do
|
|
23
22
|
subject(:instance) { model.instantiate(name: 'Hello', foo: 'Bar') }
|
|
24
23
|
|
|
25
|
-
specify { expect(subject.instance_variable_get(:@initial_attributes)).to eq({
|
|
24
|
+
specify { expect(subject.instance_variable_get(:@initial_attributes)).to eq({name: 'Hello'}.stringify_keys) }
|
|
26
25
|
end
|
|
27
26
|
end
|
|
28
27
|
|
|
@@ -31,17 +30,17 @@ describe ActiveData::Model::Persistence do
|
|
|
31
30
|
subject(:instances) { model.instantiate_collection(name: 'Hello', foo: 'Bar') }
|
|
32
31
|
|
|
33
32
|
specify { expect(subject).to be_a Array }
|
|
34
|
-
specify { expect(subject.first.instance_variable_get(:@initial_attributes)).to eq({
|
|
33
|
+
specify { expect(subject.first.instance_variable_get(:@initial_attributes)).to eq({name: 'Hello'}.stringify_keys) }
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
context do
|
|
38
37
|
before { model.send(:include, ActiveData::Model::Scopes) }
|
|
39
|
-
subject(:instances) { model.instantiate_collection([{
|
|
38
|
+
subject(:instances) { model.instantiate_collection([{name: 'Hello', foo: 'Bar'}, {name: 'World'}]) }
|
|
40
39
|
|
|
41
40
|
specify { expect(subject).to be_a ActiveData::Model::Scopes::ScopeProxy }
|
|
42
41
|
specify { expect(subject.count).to eq(2) }
|
|
43
|
-
specify { expect(subject.first.instance_variable_get(:@initial_attributes)).to eq({
|
|
44
|
-
specify { expect(subject.second.instance_variable_get(:@initial_attributes)).to eq({
|
|
42
|
+
specify { expect(subject.first.instance_variable_get(:@initial_attributes)).to eq({name: 'Hello'}.stringify_keys) }
|
|
43
|
+
specify { expect(subject.second.instance_variable_get(:@initial_attributes)).to eq({name: 'World'}.stringify_keys) }
|
|
45
44
|
end
|
|
46
45
|
end
|
|
47
46
|
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveData::Model::Representation do
|
|
4
|
+
context 'integration' do
|
|
5
|
+
before do
|
|
6
|
+
stub_model(:author) do
|
|
7
|
+
attribute :rate, Integer
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
stub_model(:post) do
|
|
11
|
+
include ActiveData::Model::Representation
|
|
12
|
+
|
|
13
|
+
attribute :author, Object
|
|
14
|
+
alias_attribute :a, :author
|
|
15
|
+
represents :rate, of: :a
|
|
16
|
+
alias_attribute :r, :rate
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
let(:author) { Author.new(rate: '42') }
|
|
20
|
+
|
|
21
|
+
specify { expect(Post.reflect_on_attribute(:rate).reference).to eq('author') }
|
|
22
|
+
|
|
23
|
+
specify { expect(Post.new(author: author).rate).to eq(42) }
|
|
24
|
+
specify { expect(Post.new(author: author).rate_before_type_cast).to eq('42') }
|
|
25
|
+
specify { expect(Post.new(rate: '33', author: author).rate).to eq(33) }
|
|
26
|
+
specify { expect(Post.new(rate: '33', author: author).author.rate).to eq(33) }
|
|
27
|
+
specify { expect(Post.new(r: '33', author: author).rate).to eq(33) }
|
|
28
|
+
specify { expect(Post.new(r: '33', author: author).author.rate).to eq(33) }
|
|
29
|
+
specify { expect(Post.new(author: author).rate?).to eq(true) }
|
|
30
|
+
specify { expect(Post.new(rate: nil, author: author).rate?).to eq(false) }
|
|
31
|
+
|
|
32
|
+
specify { expect(Post.new.rate).to be_nil }
|
|
33
|
+
specify { expect(Post.new.rate_before_type_cast).to be_nil }
|
|
34
|
+
specify { expect { Post.new(rate: '33') }.to raise_error(NoMethodError) }
|
|
35
|
+
|
|
36
|
+
context 'ActionController::Parameters' do
|
|
37
|
+
let(:params) { instance_double('ActionController::Parameters', to_unsafe_hash: {rate: '33', author: author}) }
|
|
38
|
+
specify { expect { Post.new(params) }.not_to raise_error }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'dirty' do
|
|
42
|
+
before { Post.include ActiveData::Model::Dirty }
|
|
43
|
+
|
|
44
|
+
specify do
|
|
45
|
+
expect(Post.new(author: author, rate: '33').changes)
|
|
46
|
+
.to eq('author' => [nil, author], 'rate' => [42, 33])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context do
|
|
51
|
+
before do
|
|
52
|
+
stub_class(:author, ActiveRecord::Base)
|
|
53
|
+
|
|
54
|
+
stub_model(:post) do
|
|
55
|
+
include ActiveData::Model::Associations
|
|
56
|
+
include ActiveData::Model::Representation
|
|
57
|
+
|
|
58
|
+
references_one :author
|
|
59
|
+
alias_association :a, :author
|
|
60
|
+
represents :name, of: :a
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
let!(:author) { Author.create!(name: 42) }
|
|
64
|
+
|
|
65
|
+
specify { expect(Post.reflect_on_attribute(:name).reference).to eq('author') }
|
|
66
|
+
|
|
67
|
+
specify { expect(Post.new(name: '33', author: author).name).to eq('33') }
|
|
68
|
+
specify { expect(Post.new(name: '33', author: author).author.name).to eq('33') }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context 'multiple attributes in a single represents definition' do
|
|
72
|
+
before do
|
|
73
|
+
stub_model(:author) do
|
|
74
|
+
attribute :first_name, String
|
|
75
|
+
attribute :last_name, String
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
stub_model(:post) do
|
|
79
|
+
include ActiveData::Model::Representation
|
|
80
|
+
|
|
81
|
+
attribute :author, Object
|
|
82
|
+
represents :first_name, :last_name, of: :author
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
let(:author) { Author.new(first_name: 'John', last_name: 'Doe') }
|
|
87
|
+
let(:post) { Post.new }
|
|
88
|
+
|
|
89
|
+
specify do
|
|
90
|
+
expect { post.update(author: author) }
|
|
91
|
+
.to change { post.first_name }.to('John')
|
|
92
|
+
.and change { post.last_name }.to('Doe')
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe '#validate' do
|
|
98
|
+
before do
|
|
99
|
+
stub_class(:author, ActiveRecord::Base) do
|
|
100
|
+
validates :name, presence: true
|
|
101
|
+
|
|
102
|
+
# Emulate Active Record association auto save error.
|
|
103
|
+
def errors
|
|
104
|
+
super.tap do |errors|
|
|
105
|
+
errors.add(:'user.email', 'is invalid') if errors[:'user.email'].empty?
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
stub_model(:post) do
|
|
111
|
+
include ActiveData::Model::Associations
|
|
112
|
+
include ActiveData::Model::Representation
|
|
113
|
+
|
|
114
|
+
references_one :author
|
|
115
|
+
represents :name, :email, of: :author
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
let(:post) { Post.new(author: Author.new) }
|
|
120
|
+
|
|
121
|
+
specify do
|
|
122
|
+
expect { post.validate }.to change { post.errors.messages }
|
|
123
|
+
.to(hash_including(:'author.user.email' => ['is invalid'], name: ["can't be blank"]))
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
describe ActiveData::Model::Attributes do
|
|
@@ -96,10 +95,11 @@ describe ActiveData::Model::Attributes do
|
|
|
96
95
|
let(:model) { stub_model { attribute :column, Array } }
|
|
97
96
|
|
|
98
97
|
specify { expect(model.new(column: [1, 2, 3]).column).to eq([1, 2, 3]) }
|
|
99
|
-
specify { expect(model.new(column: 'hello, world').column).to eq([
|
|
98
|
+
specify { expect(model.new(column: 'hello, world').column).to eq(%w[hello world]) }
|
|
100
99
|
specify { expect(model.new(column: 10).column).to be_nil }
|
|
101
100
|
end
|
|
102
101
|
|
|
102
|
+
# rubocop:disable Style/DateTime
|
|
103
103
|
context 'date' do
|
|
104
104
|
let(:model) { stub_model { attribute :column, Date } }
|
|
105
105
|
let(:date) { Date.new(2013, 6, 13) }
|
|
@@ -149,6 +149,7 @@ describe ActiveData::Model::Attributes do
|
|
|
149
149
|
specify { expect(model.new(column: Time.new(2013, 6, 13, 23, 13)).column).to eq(Time.new(2013, 6, 13, 23, 13)) }
|
|
150
150
|
end
|
|
151
151
|
end
|
|
152
|
+
# rubocop:enable Style/DateTime
|
|
152
153
|
|
|
153
154
|
context 'time_zone' do
|
|
154
155
|
let(:model) { stub_model { attribute :column, ActiveSupport::TimeZone } }
|
|
@@ -175,13 +176,13 @@ describe ActiveData::Model::Attributes do
|
|
|
175
176
|
let(:uuid_tools) { UUIDTools::UUID.random_create }
|
|
176
177
|
|
|
177
178
|
specify { expect(uuid.as_json).to eq(uuid.to_s) }
|
|
178
|
-
specify { expect(uuid.to_json).to eq("\"#{uuid
|
|
179
|
+
specify { expect(uuid.to_json).to eq("\"#{uuid}\"") }
|
|
179
180
|
specify { expect(uuid.to_param).to eq(uuid.to_s) }
|
|
180
|
-
specify { expect(uuid.to_query(:key)).to eq("key=#{uuid
|
|
181
|
+
specify { expect(uuid.to_query(:key)).to eq("key=#{uuid}") }
|
|
181
182
|
|
|
182
183
|
specify { expect(model.new(column: nil).column).to be_nil }
|
|
183
184
|
specify { expect(model.new(column: Object.new).column).to be_nil }
|
|
184
|
-
specify { expect(model.new(column: uuid_tools).column).to be_a ActiveData::UUID
|
|
185
|
+
specify { expect(model.new(column: uuid_tools).column).to be_a ActiveData::UUID }
|
|
185
186
|
specify { expect(model.new(column: uuid_tools).column).to eq(uuid_tools) }
|
|
186
187
|
specify { expect(model.new(column: uuid).column).to eq(uuid) }
|
|
187
188
|
specify { expect(model.new(column: uuid.to_s).column).to eq(uuid) }
|
|
@@ -35,60 +35,68 @@ describe ActiveData::Model::Validations::AssociatedValidator do
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
context do
|
|
38
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_one: {
|
|
38
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_one: {name: 'name'} }
|
|
39
39
|
it { is_expected.to be_valid }
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
context do
|
|
43
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_one: {
|
|
43
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_one: {} }
|
|
44
44
|
it { is_expected.not_to be_valid }
|
|
45
|
-
specify
|
|
46
|
-
.to
|
|
45
|
+
specify do
|
|
46
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
47
|
+
.to(validated_one: ['is invalid'])
|
|
48
|
+
end
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
context do
|
|
50
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {
|
|
52
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {name: 'name'} }
|
|
51
53
|
it { is_expected.to be_valid }
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
context do
|
|
55
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {
|
|
57
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {} }
|
|
56
58
|
it { is_expected.to be_valid }
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
context do
|
|
60
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
62
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{name: 'name'}] }
|
|
61
63
|
it { is_expected.to be_valid }
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
context do
|
|
65
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
67
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}] }
|
|
66
68
|
it { is_expected.not_to be_valid }
|
|
67
|
-
specify
|
|
68
|
-
|
|
69
|
+
specify do
|
|
70
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
71
|
+
.to(:'validated_many.0.name' => ["can't be blank"], validated_many: ['is invalid'])
|
|
72
|
+
end
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
context do
|
|
72
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{
|
|
76
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{name: 'name'}] }
|
|
73
77
|
it { is_expected.to be_valid }
|
|
74
78
|
end
|
|
75
79
|
|
|
76
80
|
context do
|
|
77
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{
|
|
81
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{}] }
|
|
78
82
|
it { is_expected.to be_valid }
|
|
79
83
|
end
|
|
80
84
|
|
|
81
85
|
context do
|
|
82
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
86
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{name: 'name'}], validated_one: {} }
|
|
83
87
|
it { is_expected.not_to be_valid }
|
|
84
|
-
specify
|
|
85
|
-
.to
|
|
88
|
+
specify do
|
|
89
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
90
|
+
.to(validated_one: ['is invalid'])
|
|
91
|
+
end
|
|
86
92
|
end
|
|
87
93
|
|
|
88
94
|
context do
|
|
89
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
95
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}], validated_one: {name: 'name'} }
|
|
90
96
|
it { is_expected.not_to be_valid }
|
|
91
|
-
specify
|
|
92
|
-
|
|
97
|
+
specify do
|
|
98
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
99
|
+
.to(:'validated_many.0.name' => ["can't be blank"], validated_many: ['is invalid'])
|
|
100
|
+
end
|
|
93
101
|
end
|
|
94
102
|
end
|
|
@@ -5,7 +5,9 @@ describe ActiveData::Model::Validations::NestedValidator do
|
|
|
5
5
|
stub_model(:validated_assoc) do
|
|
6
6
|
include ActiveData::Model
|
|
7
7
|
include ActiveData::Model::Lifecycle
|
|
8
|
+
include ActiveData::Model::Primary
|
|
8
9
|
|
|
10
|
+
primary :id, Integer
|
|
9
11
|
attribute :name, String
|
|
10
12
|
|
|
11
13
|
validates_presence_of :name
|
|
@@ -34,60 +36,129 @@ describe ActiveData::Model::Validations::NestedValidator do
|
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
context do
|
|
37
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_one: {
|
|
39
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_one: {name: 'name'} }
|
|
38
40
|
it { is_expected.to be_valid }
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
context do
|
|
42
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_one: {
|
|
44
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_one: {} }
|
|
43
45
|
it { is_expected.not_to be_valid }
|
|
44
|
-
specify
|
|
45
|
-
.to
|
|
46
|
+
specify do
|
|
47
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
48
|
+
.to(:'validated_one.name' => ["can't be blank"])
|
|
49
|
+
end
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
context do
|
|
49
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {
|
|
53
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {name: 'name'} }
|
|
50
54
|
it { is_expected.to be_valid }
|
|
51
55
|
end
|
|
52
56
|
|
|
53
57
|
context do
|
|
54
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {
|
|
58
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {} }
|
|
55
59
|
it { is_expected.to be_valid }
|
|
56
60
|
end
|
|
57
61
|
|
|
58
62
|
context do
|
|
59
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
63
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{name: 'name'}] }
|
|
60
64
|
it { is_expected.to be_valid }
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
context do
|
|
64
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
68
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}] }
|
|
65
69
|
it { is_expected.not_to be_valid }
|
|
66
|
-
specify
|
|
67
|
-
.to
|
|
70
|
+
specify do
|
|
71
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
72
|
+
.to(:'validated_many.0.name' => ["can't be blank"])
|
|
73
|
+
end
|
|
68
74
|
end
|
|
69
75
|
|
|
70
76
|
context do
|
|
71
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{
|
|
77
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{name: 'name'}] }
|
|
72
78
|
it { is_expected.to be_valid }
|
|
73
79
|
end
|
|
74
80
|
|
|
75
81
|
context do
|
|
76
|
-
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{
|
|
82
|
+
subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{}] }
|
|
77
83
|
it { is_expected.to be_valid }
|
|
78
84
|
end
|
|
79
85
|
|
|
80
86
|
context do
|
|
81
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
87
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{name: 'name'}], validated_one: {} }
|
|
82
88
|
it { is_expected.not_to be_valid }
|
|
83
|
-
specify
|
|
84
|
-
.to
|
|
89
|
+
specify do
|
|
90
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
91
|
+
.to(:'validated_one.name' => ["can't be blank"])
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'accepts nested attributes for one' do
|
|
96
|
+
before { Main.accepts_nested_attributes_for :validated_one, allow_destroy: true }
|
|
97
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_one: {id: 1, name: 'name'} }
|
|
98
|
+
|
|
99
|
+
specify do
|
|
100
|
+
instance.validated_one_attributes = {id: 1, name: '', _destroy: true}
|
|
101
|
+
is_expected.to be_valid
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
context 'accepts nested attributes for many' do
|
|
106
|
+
before { Main.accepts_nested_attributes_for :validated_many, allow_destroy: true }
|
|
107
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{id: 1, name: 'name'}] }
|
|
108
|
+
|
|
109
|
+
specify do
|
|
110
|
+
instance.validated_many_attributes = [{id: 1, name: '', _destroy: true}]
|
|
111
|
+
is_expected.to be_valid
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'object field is invalid and referenced object does not include AutosaveAssociation' do
|
|
116
|
+
before do
|
|
117
|
+
stub_class(:validated_object) do
|
|
118
|
+
include ActiveData::Model::Validations
|
|
119
|
+
include ActiveData::Model::Attributes
|
|
120
|
+
include ActiveData::Model::Primary
|
|
121
|
+
|
|
122
|
+
primary :id
|
|
123
|
+
attribute :title, String
|
|
124
|
+
validates_presence_of :title
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
Main.class_eval do
|
|
128
|
+
include ActiveData::Model::Associations
|
|
129
|
+
attribute :object, Object
|
|
130
|
+
validates :object, nested: true
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
subject(:instance) { Main.instantiate name: 'hello', object: object, validated_one: {name: 'name'} }
|
|
135
|
+
|
|
136
|
+
context do
|
|
137
|
+
let(:object) { ValidatedObject.new(title: 'Mr.') }
|
|
138
|
+
it { is_expected.to be_valid }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context do
|
|
142
|
+
let(:object) { ValidatedObject.new }
|
|
143
|
+
it do
|
|
144
|
+
expect { subject.valid? }.not_to raise_error
|
|
145
|
+
expect(subject).not_to be_valid
|
|
146
|
+
end
|
|
147
|
+
end
|
|
85
148
|
end
|
|
86
149
|
|
|
87
150
|
context do
|
|
88
|
-
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{
|
|
151
|
+
subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}], validated_one: {name: 'name'} }
|
|
89
152
|
it { is_expected.not_to be_valid }
|
|
90
|
-
specify
|
|
91
|
-
.to
|
|
153
|
+
specify do
|
|
154
|
+
expect { instance.validate }.to change { instance.errors.messages }
|
|
155
|
+
.to(:'validated_many.0.name' => ["can't be blank"])
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe '.validates_nested?' do
|
|
160
|
+
specify { expect(Main).to be_validates_nested(:validated_one) }
|
|
161
|
+
specify { expect(Main).to be_validates_nested(:unvalidated_one) }
|
|
162
|
+
specify { expect(Main).not_to be_validates_nested(:something_else) }
|
|
92
163
|
end
|
|
93
164
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
describe ActiveData::Model do
|
|
@@ -6,6 +5,6 @@ describe ActiveData::Model do
|
|
|
6
5
|
specify { expect { model.blablabla }.to raise_error NoMethodError }
|
|
7
6
|
|
|
8
7
|
context 'Fault tolerance' do
|
|
9
|
-
specify{ expect { model.new(foo: 'bar') }.not_to raise_error }
|
|
8
|
+
specify { expect { model.new(foo: 'bar') }.not_to raise_error }
|
|
10
9
|
end
|
|
11
10
|
end
|