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,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
|