active_data 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,16 +1,16 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'spec_helper'
|
3
2
|
|
4
3
|
describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
5
4
|
before do
|
6
5
|
stub_class(:author, ActiveRecord::Base) do
|
7
|
-
scope :name_starts_with_a, -> {
|
6
|
+
scope :name_starts_with_a, -> { name_starts_with('a') }
|
7
|
+
scope :name_starts_with, ->(letter) { where("name LIKE '#{letter}%'") }
|
8
8
|
end
|
9
9
|
|
10
10
|
stub_model(:book) do
|
11
11
|
include ActiveData::Model::Associations
|
12
12
|
|
13
|
-
attribute :title
|
13
|
+
attribute :title, String
|
14
14
|
references_many :authors
|
15
15
|
end
|
16
16
|
end
|
@@ -27,17 +27,21 @@ describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
|
27
27
|
stub_model(:book) do
|
28
28
|
include ActiveData::Model::Associations
|
29
29
|
|
30
|
-
attribute :title
|
30
|
+
attribute :title, String
|
31
31
|
references_many :creators, class_name: 'Author'
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
let(:book) { Book.new }
|
36
36
|
|
37
|
-
specify
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
specify do
|
38
|
+
expect { book.creators << author }
|
39
|
+
.to change { book.creators }.from([]).to([author])
|
40
|
+
end
|
41
|
+
specify do
|
42
|
+
expect { book.creators << author }
|
43
|
+
.to change { book.creator_ids }.from([]).to([author.id])
|
44
|
+
end
|
41
45
|
end
|
42
46
|
|
43
47
|
describe ':primary_key' do
|
@@ -51,10 +55,14 @@ describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
|
51
55
|
|
52
56
|
let(:author) { Author.create!(name: 'Rick') }
|
53
57
|
|
54
|
-
specify
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
+
specify do
|
59
|
+
expect { book.author_names = [author.name] }
|
60
|
+
.to change { book.authors }.from([]).to([author])
|
61
|
+
end
|
62
|
+
specify do
|
63
|
+
expect { book.authors = [author] }
|
64
|
+
.to change { book.author_names }.from([]).to([author.name])
|
65
|
+
end
|
58
66
|
end
|
59
67
|
|
60
68
|
describe ':reference_key' do
|
@@ -67,10 +75,14 @@ describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
|
67
75
|
|
68
76
|
let(:author) { Author.create!(name: 'Rick') }
|
69
77
|
|
70
|
-
specify
|
71
|
-
|
72
|
-
|
73
|
-
|
78
|
+
specify do
|
79
|
+
expect { book.identify = [author.id] }
|
80
|
+
.to change { book.authors }.from([]).to([author])
|
81
|
+
end
|
82
|
+
specify do
|
83
|
+
expect { book.authors = [author] }
|
84
|
+
.to change { book.identify }.from([]).to([author.id])
|
85
|
+
end
|
74
86
|
end
|
75
87
|
|
76
88
|
describe ':default' do
|
@@ -146,30 +158,63 @@ describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
|
146
158
|
it_behaves_like :new_record_default, -> { Author.new(name: 'Author') }
|
147
159
|
end
|
148
160
|
|
161
|
+
describe 'Book.inspect' do
|
162
|
+
specify { expect(Book.inspect).to eq('Book(authors: ReferencesMany(Author), title: String, author_ids: (reference))') }
|
163
|
+
end
|
164
|
+
|
149
165
|
describe '#scope' do
|
150
166
|
before do
|
151
167
|
stub_model(:book) do
|
152
168
|
include ActiveData::Model::Associations
|
153
|
-
references_many :authors, -> {
|
169
|
+
references_many :authors, ->(owner) { name_starts_with(owner.letter) }
|
170
|
+
attribute :letter, String
|
154
171
|
end
|
155
172
|
end
|
156
173
|
|
174
|
+
let(:book) { Book.new(letter: 'a') }
|
157
175
|
let!(:author1) { Author.create!(name: 'Rick') }
|
158
176
|
let!(:author2) { Author.create!(name: 'Aaron') }
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
specify
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
specify
|
170
|
-
|
171
|
-
|
172
|
-
|
177
|
+
|
178
|
+
specify do
|
179
|
+
expect { book.authors = [author1, author2] }
|
180
|
+
.to change { book.authors }.from([]).to([author1, author2])
|
181
|
+
end
|
182
|
+
specify do
|
183
|
+
expect { book.authors = [author1, author2] }
|
184
|
+
.to change { book.author_ids }.from([]).to([author1.id, author2.id])
|
185
|
+
end
|
186
|
+
|
187
|
+
specify do
|
188
|
+
expect { book.author_ids = [author1.id, author2.id] }
|
189
|
+
.to change { book.authors }.from([]).to([author2])
|
190
|
+
end
|
191
|
+
specify do
|
192
|
+
expect { book.author_ids = [author1.id, author2.id] }
|
193
|
+
.to change { book.author_ids }.from([]).to([author2.id])
|
194
|
+
end
|
195
|
+
|
196
|
+
specify do
|
197
|
+
expect { book.authors = [author1, author2] }
|
198
|
+
.to change { book.authors.reload }.from([]).to([author2])
|
199
|
+
end
|
200
|
+
specify do
|
201
|
+
expect { book.authors = [author1, author2] }
|
202
|
+
.to change {
|
203
|
+
book.authors.reload
|
204
|
+
book.author_ids
|
205
|
+
}.from([]).to([author2.id])
|
206
|
+
end
|
207
|
+
|
208
|
+
context do
|
209
|
+
let(:book2) { Book.new(letter: 'r') }
|
210
|
+
|
211
|
+
specify 'scope is not cached too much' do
|
212
|
+
expect { book.author_ids = [author1.id, author2.id] }
|
213
|
+
.to change { book.authors }.from([]).to([author2])
|
214
|
+
expect { book2.author_ids = [author1.id, author2.id] }
|
215
|
+
.to change { book2.authors }.from([]).to([author1])
|
216
|
+
end
|
217
|
+
end
|
173
218
|
end
|
174
219
|
|
175
220
|
describe '#author' do
|
@@ -227,8 +272,10 @@ describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
|
227
272
|
|
228
273
|
context do
|
229
274
|
before { book.authors = [author, other] }
|
230
|
-
specify
|
231
|
-
.to(
|
275
|
+
specify do
|
276
|
+
expect { author.save! }.to change { book.author_ids }.from([nil, other.id])
|
277
|
+
.to(match([be_a(Integer), other.id]))
|
278
|
+
end
|
232
279
|
specify { expect { author.save! }.not_to change { book.authors } }
|
233
280
|
end
|
234
281
|
end
|
@@ -237,6 +284,7 @@ describe ActiveData::Model::Associations::Reflections::ReferencesMany do
|
|
237
284
|
describe '#author_ids=' do
|
238
285
|
specify { expect { book.author_ids = [author.id] }.to change { book.author_ids }.from([]).to([author.id]) }
|
239
286
|
specify { expect { book.author_ids = [author.id] }.to change { book.authors }.from([]).to([author]) }
|
287
|
+
specify { expect { book.author_ids = [author] }.to change { book.authors }.from([]).to([author]) }
|
240
288
|
|
241
289
|
specify { expect { book.author_ids = [author.id.next.to_s] }.not_to change { book.author_ids }.from([]) }
|
242
290
|
specify { expect { book.author_ids = [author.id.next.to_s] }.not_to change { book.authors }.from([]) }
|
@@ -1,16 +1,16 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'spec_helper'
|
3
2
|
|
4
3
|
describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
5
4
|
before do
|
6
5
|
stub_class(:author, ActiveRecord::Base) do
|
7
|
-
scope :name_starts_with_a, -> {
|
6
|
+
scope :name_starts_with_a, -> { name_starts_with('a') }
|
7
|
+
scope :name_starts_with, ->(letter) { where("name LIKE '#{letter}%'") }
|
8
8
|
end
|
9
9
|
|
10
10
|
stub_model(:book) do
|
11
11
|
include ActiveData::Model::Associations
|
12
12
|
|
13
|
-
attribute :title
|
13
|
+
attribute :title, String
|
14
14
|
references_one :author
|
15
15
|
end
|
16
16
|
end
|
@@ -23,16 +23,20 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
23
23
|
stub_model(:book) do
|
24
24
|
include ActiveData::Model::Associations
|
25
25
|
|
26
|
-
attribute :title
|
26
|
+
attribute :title, String
|
27
27
|
references_one :creator, class_name: 'Author'
|
28
28
|
end
|
29
29
|
end
|
30
30
|
let(:author) { Author.create!(name: 'Rick') }
|
31
31
|
|
32
|
-
specify
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
specify do
|
33
|
+
expect { book.creator = author }
|
34
|
+
.to change { book.creator }.from(nil).to(author)
|
35
|
+
end
|
36
|
+
specify do
|
37
|
+
expect { book.creator = author }
|
38
|
+
.to change { book.creator_id }.from(nil).to(author.id)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
describe ':primary_key' do
|
@@ -46,10 +50,14 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
46
50
|
|
47
51
|
let(:author) { Author.create!(name: 'Rick') }
|
48
52
|
|
49
|
-
specify
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
+
specify do
|
54
|
+
expect { book.author_name = author.name }
|
55
|
+
.to change { book.author }.from(nil).to(author)
|
56
|
+
end
|
57
|
+
specify do
|
58
|
+
expect { book.author = author }
|
59
|
+
.to change { book.author_name }.from(nil).to(author.name)
|
60
|
+
end
|
53
61
|
end
|
54
62
|
|
55
63
|
describe ':reference_key' do
|
@@ -62,10 +70,14 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
62
70
|
|
63
71
|
let(:author) { Author.create!(name: 'Rick') }
|
64
72
|
|
65
|
-
specify
|
66
|
-
|
67
|
-
|
68
|
-
|
73
|
+
specify do
|
74
|
+
expect { book.identify = author.id }
|
75
|
+
.to change { book.author }.from(nil).to(author)
|
76
|
+
end
|
77
|
+
specify do
|
78
|
+
expect { book.author = author }
|
79
|
+
.to change { book.identify }.from(nil).to(author.id)
|
80
|
+
end
|
69
81
|
end
|
70
82
|
|
71
83
|
describe ':default' do
|
@@ -129,36 +141,81 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
129
141
|
it_behaves_like :new_record_default, -> { Author.new(name: 'Author') }
|
130
142
|
end
|
131
143
|
|
144
|
+
describe 'Book.inspect' do
|
145
|
+
specify { expect(Book.inspect).to eq('Book(author: ReferencesOne(Author), title: String, author_id: (reference))') }
|
146
|
+
end
|
147
|
+
|
132
148
|
describe '#scope' do
|
133
149
|
before do
|
134
150
|
stub_model(:book) do
|
135
151
|
include ActiveData::Model::Associations
|
136
|
-
references_one :author, -> {
|
152
|
+
references_one :author, ->(owner) { name_starts_with(owner.letter) }
|
153
|
+
attribute :letter, String
|
137
154
|
end
|
138
155
|
end
|
139
156
|
|
157
|
+
let(:book) { Book.new(letter: 'a') }
|
140
158
|
let!(:author1) { Author.create!(name: 'Rick') }
|
141
159
|
let!(:author2) { Author.create!(name: 'Aaron') }
|
142
160
|
|
143
|
-
specify
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
161
|
+
specify do
|
162
|
+
expect { book.author_id = author1.id }
|
163
|
+
.not_to change { book.author }
|
164
|
+
end
|
165
|
+
specify do
|
166
|
+
expect { book.author_id = author2.id }
|
167
|
+
.to change { book.author }.from(nil).to(author2)
|
168
|
+
end
|
169
|
+
|
170
|
+
specify do
|
171
|
+
expect { book.author = author1 }
|
172
|
+
.to change { book.author_id }.from(nil).to(author1.id)
|
173
|
+
end
|
174
|
+
specify do
|
175
|
+
expect { book.author = author2 }
|
176
|
+
.to change { book.author_id }.from(nil).to(author2.id)
|
177
|
+
end
|
178
|
+
|
179
|
+
specify do
|
180
|
+
expect { book.author = author1 }
|
181
|
+
.to change {
|
182
|
+
book.association(:author).reload
|
183
|
+
book.author_id
|
184
|
+
}.from(nil).to(author1.id)
|
185
|
+
end
|
186
|
+
specify do
|
187
|
+
expect { book.author = author2 }
|
188
|
+
.to change {
|
189
|
+
book.association(:author).reload
|
190
|
+
book.author_id
|
191
|
+
}.from(nil).to(author2.id)
|
192
|
+
end
|
193
|
+
|
194
|
+
specify do
|
195
|
+
expect { book.author = author1 }
|
196
|
+
.not_to change {
|
197
|
+
book.association(:author).reload
|
198
|
+
book.author
|
199
|
+
}
|
200
|
+
end
|
201
|
+
specify do
|
202
|
+
expect { book.author = author2 }
|
203
|
+
.to change {
|
204
|
+
book.association(:author).reload
|
205
|
+
book.author
|
206
|
+
}.from(nil).to(author2)
|
207
|
+
end
|
208
|
+
|
209
|
+
context do
|
210
|
+
let(:book2) { Book.new(letter: 'r') }
|
211
|
+
|
212
|
+
specify 'scope is not cached too much' do
|
213
|
+
expect { book.author_id = author2.id }
|
214
|
+
.to change { book.author }.from(nil).to(author2)
|
215
|
+
expect { book2.author_id = author1.id }
|
216
|
+
.to change { book2.author }.from(nil).to(author1)
|
217
|
+
end
|
218
|
+
end
|
162
219
|
end
|
163
220
|
|
164
221
|
describe '#author=' do
|
@@ -182,7 +239,7 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
182
239
|
|
183
240
|
context do
|
184
241
|
before { book.author = author }
|
185
|
-
specify { expect { author.save! }.to change { book.author_id }.from(nil).to(
|
242
|
+
specify { expect { author.save! }.to change { book.author_id }.from(nil).to(be_a(Integer)) }
|
186
243
|
specify { expect { author.save! }.not_to change { book.author } }
|
187
244
|
end
|
188
245
|
end
|
@@ -192,6 +249,7 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
192
249
|
let(:author) { Author.create!(name: 'Author') }
|
193
250
|
specify { expect { book.author_id = author.id }.to change { book.author_id }.from(nil).to(author.id) }
|
194
251
|
specify { expect { book.author_id = author.id }.to change { book.author }.from(nil).to(author) }
|
252
|
+
specify { expect { book.author_id = author }.to change { book.author }.from(nil).to(author) }
|
195
253
|
|
196
254
|
specify { expect { book.author_id = author.id.next.to_s }.to change { book.author_id }.from(nil).to(author.id.next) }
|
197
255
|
specify { expect { book.author_id = author.id.next.to_s }.not_to change { book.author }.from(nil) }
|
@@ -205,4 +263,25 @@ describe ActiveData::Model::Associations::Reflections::ReferencesOne do
|
|
205
263
|
specify { expect { book.author_id = nil }.to change { book.author }.from(other).to(nil) }
|
206
264
|
end
|
207
265
|
end
|
266
|
+
|
267
|
+
describe '#build_author' do
|
268
|
+
specify { expect(book.build_author(name: 'Author')).to be_a(Author) }
|
269
|
+
specify { expect(book.build_author(name: 'Author')).not_to be_persisted }
|
270
|
+
specify { expect { book.build_author(name: 'Author') }.to change { book.author }.from(nil).to(an_instance_of(Author)) }
|
271
|
+
specify { expect { book.build_author(name: 'Author') }.not_to change { book.author_id }.from(nil) }
|
272
|
+
end
|
273
|
+
|
274
|
+
describe '#create_author' do
|
275
|
+
specify { expect(book.create_author(name: 'Author')).to be_a(Author) }
|
276
|
+
specify { expect(book.create_author(name: 'Author')).to be_persisted }
|
277
|
+
specify { expect { book.create_author(name: 'Author') }.to change { book.author }.from(nil).to(an_instance_of(Author)) }
|
278
|
+
specify { expect { book.create_author(name: 'Author') }.to change { book.author_id }.from(nil).to(be_a(Integer)) }
|
279
|
+
end
|
280
|
+
|
281
|
+
describe '#create_author!' do
|
282
|
+
specify { expect(book.create_author!(name: 'Author')).to be_a(Author) }
|
283
|
+
specify { expect(book.create_author!(name: 'Author')).to be_persisted }
|
284
|
+
specify { expect { book.create_author!(name: 'Author') }.to change { book.author }.from(nil).to(an_instance_of(Author)) }
|
285
|
+
specify { expect { book.create_author!(name: 'Author') }.to change { book.author_id }.from(nil).to(be_a(Integer)) }
|
286
|
+
end
|
208
287
|
end
|
@@ -5,6 +5,7 @@ describe ActiveData::Model::Associations::Validations do
|
|
5
5
|
stub_model(:project) do
|
6
6
|
include ActiveData::Model::Lifecycle
|
7
7
|
include ActiveData::Model::Associations
|
8
|
+
include ActiveData::Model::Associations::Validations
|
8
9
|
|
9
10
|
attribute :title, String
|
10
11
|
validates :title, presence: true
|
@@ -25,6 +26,7 @@ describe ActiveData::Model::Associations::Validations do
|
|
25
26
|
|
26
27
|
stub_model(:user) do
|
27
28
|
include ActiveData::Model::Associations
|
29
|
+
include ActiveData::Model::Associations::Validations
|
28
30
|
|
29
31
|
attribute :login, String
|
30
32
|
validates :login, presence: true
|
@@ -39,7 +41,7 @@ describe ActiveData::Model::Associations::Validations do
|
|
39
41
|
let(:project) { Project.new title: 'Project' }
|
40
42
|
let(:projects) { [project] }
|
41
43
|
let(:user) { User.new(login: 'Login', profile: profile, projects: projects) }
|
42
|
-
let(:author_attributes) { {
|
44
|
+
let(:author_attributes) { {name: 'Author'} }
|
43
45
|
before { project.build_author(author_attributes) }
|
44
46
|
|
45
47
|
specify { expect(user.validate).to eq(true) }
|
@@ -49,8 +51,10 @@ describe ActiveData::Model::Associations::Validations do
|
|
49
51
|
let(:author_attributes) { {} }
|
50
52
|
|
51
53
|
specify { expect(user.validate).to eq(false) }
|
52
|
-
specify
|
53
|
-
.to
|
54
|
+
specify do
|
55
|
+
expect { user.validate }.to change { user.errors.messages }
|
56
|
+
.to(:'projects.0.author.name' => ["can't be blank"])
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
context do
|
@@ -64,8 +68,10 @@ describe ActiveData::Model::Associations::Validations do
|
|
64
68
|
let(:projects) { [project, Project.new] }
|
65
69
|
|
66
70
|
specify { expect(user.validate).to eq(false) }
|
67
|
-
specify
|
68
|
-
.to
|
71
|
+
specify do
|
72
|
+
expect { user.validate }.to change { user.errors.messages }
|
73
|
+
.to(:'projects.1.title' => ["can't be blank"])
|
74
|
+
end
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
@@ -74,7 +80,7 @@ describe ActiveData::Model::Associations::Validations do
|
|
74
80
|
let(:project) { Project.new title: 'Project' }
|
75
81
|
let(:projects) { [project] }
|
76
82
|
let(:user) { User.new(login: 'Login', profile: profile, projects: projects) }
|
77
|
-
let(:author_attributes) { {
|
83
|
+
let(:author_attributes) { {name: 'Author'} }
|
78
84
|
before { project.build_author(author_attributes) }
|
79
85
|
|
80
86
|
specify { expect(user.validate_ancestry).to eq(true) }
|
@@ -90,8 +96,10 @@ describe ActiveData::Model::Associations::Validations do
|
|
90
96
|
specify { expect { user.validate_ancestry! }.to raise_error ActiveData::ValidationError }
|
91
97
|
specify { expect(user.valid_ancestry?).to eq(false) }
|
92
98
|
specify { expect(user.invalid_ancestry?).to eq(true) }
|
93
|
-
specify
|
94
|
-
.to
|
99
|
+
specify do
|
100
|
+
expect { user.validate_ancestry }.to change { user.errors.messages }
|
101
|
+
.to(:'projects.0.author.name' => ["can't be blank"])
|
102
|
+
end
|
95
103
|
end
|
96
104
|
|
97
105
|
context do
|
@@ -100,8 +108,10 @@ describe ActiveData::Model::Associations::Validations do
|
|
100
108
|
specify { expect { user.validate_ancestry! }.to raise_error ActiveData::ValidationError }
|
101
109
|
specify { expect(user.valid_ancestry?).to eq(false) }
|
102
110
|
specify { expect(user.invalid_ancestry?).to eq(true) }
|
103
|
-
specify
|
104
|
-
.to
|
111
|
+
specify do
|
112
|
+
expect { user.validate_ancestry }.to change { user.errors.messages }
|
113
|
+
.to(:'profile.first_name' => ["can't be blank"])
|
114
|
+
end
|
105
115
|
end
|
106
116
|
|
107
117
|
context do
|
@@ -110,44 +120,18 @@ describe ActiveData::Model::Associations::Validations do
|
|
110
120
|
specify { expect { user.validate_ancestry! }.to raise_error ActiveData::ValidationError }
|
111
121
|
specify { expect(user.valid_ancestry?).to eq(false) }
|
112
122
|
specify { expect(user.invalid_ancestry?).to eq(true) }
|
113
|
-
specify
|
114
|
-
.to
|
123
|
+
specify do
|
124
|
+
expect { user.validate_ancestry }.to change { user.errors.messages }
|
125
|
+
.to(:'projects.1.title' => ["can't be blank"])
|
126
|
+
end
|
115
127
|
|
116
128
|
context do
|
117
129
|
before { user.update(login: '') }
|
118
|
-
specify
|
119
|
-
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
context 'represent attributes' do
|
125
|
-
before do
|
126
|
-
stub_class(:author, ActiveRecord::Base) do
|
127
|
-
validates :name, presence: true
|
128
|
-
|
129
|
-
# Emulate Active Record association auto save error.
|
130
|
-
def errors
|
131
|
-
super.tap do |errors|
|
132
|
-
errors.add(:'user.email', 'is invalid') if errors[:'user.email'].empty?
|
133
|
-
end
|
130
|
+
specify do
|
131
|
+
expect { user.validate_ancestry }.to change { user.errors.messages }
|
132
|
+
.to(:'projects.1.title' => ["can't be blank"], login: ["can't be blank"])
|
134
133
|
end
|
135
134
|
end
|
136
|
-
|
137
|
-
stub_model(:post) do
|
138
|
-
include ActiveData::Model::Associations
|
139
|
-
|
140
|
-
references_one :author
|
141
|
-
represents :name, of: :author
|
142
|
-
represents :email, of: :author
|
143
|
-
end
|
144
135
|
end
|
145
|
-
|
146
|
-
let(:post) { Post.new(author: Author.new) }
|
147
|
-
|
148
|
-
specify { expect { post.validate_ancestry }.to change { post.errors.messages }
|
149
|
-
.to(hash_including(:'author.user.email' => ['is invalid'], name: ["can't be blank"])) }
|
150
|
-
specify { expect { post.validate }.to change { post.errors.messages }
|
151
|
-
.to(hash_including(:'author.user.email' => ['is invalid'], name: ["can't be blank"])) }
|
152
136
|
end
|
153
137
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'spec_helper'
|
3
2
|
|
4
3
|
describe ActiveData::Model::Associations do
|
@@ -30,7 +29,7 @@ describe ActiveData::Model::Associations do
|
|
30
29
|
specify { expect(Nobody.reflections.keys).to eq([]) }
|
31
30
|
specify { expect(User.reflections.keys).to eq([:projects]) }
|
32
31
|
specify { expect(Manager.reflections.keys).to eq([:managed_project]) }
|
33
|
-
specify { expect(Admin.reflections.keys).to eq([
|
32
|
+
specify { expect(Admin.reflections.keys).to eq(%i[projects admin_projects]) }
|
34
33
|
end
|
35
34
|
|
36
35
|
describe '#reflect_on_association' do
|
@@ -43,21 +42,23 @@ describe ActiveData::Model::Associations do
|
|
43
42
|
|
44
43
|
context 'class determine errors' do
|
45
44
|
specify do
|
46
|
-
expect
|
47
|
-
|
45
|
+
expect do
|
46
|
+
stub_model do
|
47
|
+
include ActiveData::Model::Associations
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
embeds_one :author, class_name: 'Borogoves'
|
50
|
+
end.reflect_on_association(:author).data_source end.to raise_error NameError
|
51
51
|
end
|
52
52
|
|
53
53
|
specify do
|
54
|
-
expect
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
54
|
+
expect do
|
55
|
+
stub_model(:user) do
|
56
|
+
include ActiveData::Model::Associations
|
57
|
+
|
58
|
+
embeds_many :projects, class_name: 'Borogoves' do
|
59
|
+
attribute :title
|
60
|
+
end
|
61
|
+
end.reflect_on_association(:projects).data_source end.to raise_error NameError
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
@@ -103,22 +104,24 @@ describe ActiveData::Model::Associations do
|
|
103
104
|
|
104
105
|
let(:user) { User.new }
|
105
106
|
|
106
|
-
|
107
|
-
|
107
|
+
specify { expect(user.projects).to eq([]) }
|
108
|
+
specify { expect(user.profile).to be_nil }
|
108
109
|
|
109
110
|
describe '.inspect' do
|
110
111
|
specify { expect(User.inspect).to eq('User(profile: EmbedsOne(Profile), projects: EmbedsMany(Project), login: Object)') }
|
111
112
|
end
|
112
113
|
|
113
114
|
describe '.association_names' do
|
114
|
-
specify { expect(User.association_names).to eq([
|
115
|
+
specify { expect(User.association_names).to eq(%i[profile projects]) }
|
115
116
|
end
|
116
117
|
|
117
118
|
describe '#inspect' do
|
118
119
|
let(:profile) { Profile.new first_name: 'Name' }
|
119
120
|
let(:project) { Project.new title: 'Project' }
|
120
|
-
specify
|
121
|
-
.
|
121
|
+
specify do
|
122
|
+
expect(User.new(login: 'Login', profile: profile, projects: [project]).inspect)
|
123
|
+
.to eq('#<User profile: #<EmbedsOne #<Profile first_name: "Name", last_name: nil>>, projects: #<EmbedsMany [#<Project author: #<EmbedsOne nil>, title: "P...]>, login: "Login">')
|
124
|
+
end
|
122
125
|
end
|
123
126
|
|
124
127
|
describe '#==' do
|
@@ -154,7 +157,7 @@ describe ActiveData::Model::Associations do
|
|
154
157
|
end
|
155
158
|
|
156
159
|
describe '#association_names' do
|
157
|
-
specify { expect(user.association_names).to eq([
|
160
|
+
specify { expect(user.association_names).to eq(%i[profile projects]) }
|
158
161
|
end
|
159
162
|
|
160
163
|
describe '#apply_association_changes!' do
|
@@ -163,10 +166,14 @@ describe ActiveData::Model::Associations do
|
|
163
166
|
let(:user) { User.new(profile: profile, projects: [project]) }
|
164
167
|
before { project.build_author(name: 'Author') }
|
165
168
|
|
166
|
-
specify
|
167
|
-
.
|
168
|
-
|
169
|
-
|
169
|
+
specify do
|
170
|
+
expect { user.apply_association_changes! }.to change { user.attributes['profile'] }
|
171
|
+
.from(nil).to('first_name' => 'Name', 'last_name' => nil)
|
172
|
+
end
|
173
|
+
specify do
|
174
|
+
expect { user.apply_association_changes! }.to change { user.attributes['projects'] }
|
175
|
+
.from(nil).to([{'title' => 'Project', 'author' => {'name' => 'Author'}}])
|
176
|
+
end
|
170
177
|
|
171
178
|
context do
|
172
179
|
let(:project) { Project.new }
|
@@ -182,8 +189,10 @@ describe ActiveData::Model::Associations do
|
|
182
189
|
before { project.build_author(name: 'Author') }
|
183
190
|
|
184
191
|
specify { expect(User.instantiate(JSON.parse(user.to_json))).to eq(user) }
|
185
|
-
specify
|
186
|
-
.
|
192
|
+
specify do
|
193
|
+
expect(User.instantiate(JSON.parse(user.to_json))
|
194
|
+
.tap { |u| u.projects.first.author.name = 'Other' }).not_to eq(user)
|
195
|
+
end
|
187
196
|
end
|
188
197
|
end
|
189
198
|
end
|