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.
Files changed (115) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +13 -0
  3. data/.rubocop.yml +56 -0
  4. data/.rubocop_todo.yml +53 -0
  5. data/.rvmrc +1 -1
  6. data/.travis.yml +15 -2
  7. data/Appraisals +1 -1
  8. data/CHANGELOG.md +31 -0
  9. data/Guardfile +8 -8
  10. data/README.md +256 -0
  11. data/Rakefile +2 -4
  12. data/active_data.gemspec +8 -7
  13. data/gemfiles/rails.4.0.gemfile +1 -1
  14. data/gemfiles/rails.4.1.gemfile +1 -1
  15. data/gemfiles/rails.4.2.gemfile +1 -1
  16. data/gemfiles/rails.5.0.gemfile +1 -1
  17. data/gemfiles/rails.5.1.gemfile +14 -0
  18. data/lib/active_data/active_record/associations.rb +18 -13
  19. data/lib/active_data/active_record/nested_attributes.rb +8 -14
  20. data/lib/active_data/base.rb +13 -0
  21. data/lib/active_data/config.rb +4 -4
  22. data/lib/active_data/errors.rb +29 -13
  23. data/lib/active_data/extensions.rb +22 -21
  24. data/lib/active_data/model/associations/base.rb +22 -6
  25. data/lib/active_data/model/associations/embeds_any.rb +17 -0
  26. data/lib/active_data/model/associations/embeds_many.rb +29 -19
  27. data/lib/active_data/model/associations/embeds_one.rb +30 -26
  28. data/lib/active_data/model/associations/nested_attributes.rb +82 -50
  29. data/lib/active_data/model/associations/persistence_adapters/active_record/referenced_proxy.rb +31 -0
  30. data/lib/active_data/model/associations/persistence_adapters/active_record.rb +66 -0
  31. data/lib/active_data/model/associations/persistence_adapters/base.rb +53 -0
  32. data/lib/active_data/model/associations/references_any.rb +41 -0
  33. data/lib/active_data/model/associations/references_many.rb +51 -37
  34. data/lib/active_data/model/associations/references_one.rb +43 -41
  35. data/lib/active_data/model/associations/reflections/base.rb +19 -29
  36. data/lib/active_data/model/associations/reflections/embeds_any.rb +43 -0
  37. data/lib/active_data/model/associations/reflections/embeds_many.rb +3 -13
  38. data/lib/active_data/model/associations/reflections/embeds_one.rb +5 -37
  39. data/lib/active_data/model/associations/reflections/references_any.rb +62 -0
  40. data/lib/active_data/model/associations/reflections/references_many.rb +7 -7
  41. data/lib/active_data/model/associations/reflections/references_one.rb +9 -7
  42. data/lib/active_data/model/associations/reflections/singular.rb +35 -0
  43. data/lib/active_data/model/associations/validations.rb +2 -27
  44. data/lib/active_data/model/associations.rb +12 -10
  45. data/lib/active_data/model/attributes/attribute.rb +10 -10
  46. data/lib/active_data/model/attributes/base.rb +8 -7
  47. data/lib/active_data/model/attributes/localized.rb +4 -4
  48. data/lib/active_data/model/attributes/reference_many.rb +6 -8
  49. data/lib/active_data/model/attributes/reference_one.rb +17 -9
  50. data/lib/active_data/model/attributes/reflections/attribute.rb +2 -2
  51. data/lib/active_data/model/attributes/reflections/base.rb +8 -11
  52. data/lib/active_data/model/attributes/reflections/localized.rb +2 -2
  53. data/lib/active_data/model/attributes/reflections/reference_one.rb +11 -22
  54. data/lib/active_data/model/attributes/reflections/represents.rb +5 -6
  55. data/lib/active_data/model/attributes/represents.rb +6 -5
  56. data/lib/active_data/model/attributes.rb +33 -87
  57. data/lib/active_data/model/callbacks.rb +6 -7
  58. data/lib/active_data/model/conventions.rb +2 -0
  59. data/lib/active_data/model/dirty.rb +4 -4
  60. data/lib/active_data/model/lifecycle.rb +18 -20
  61. data/lib/active_data/model/localization.rb +5 -2
  62. data/lib/active_data/model/persistence.rb +2 -2
  63. data/lib/active_data/model/primary.rb +19 -14
  64. data/lib/active_data/model/representation.rb +81 -0
  65. data/lib/active_data/model/scopes.rb +22 -12
  66. data/lib/active_data/model/validations/associated.rb +3 -2
  67. data/lib/active_data/model/validations/nested.rb +6 -1
  68. data/lib/active_data/model/validations.rb +3 -3
  69. data/lib/active_data/model.rb +2 -1
  70. data/lib/active_data/undefined_class.rb +9 -0
  71. data/lib/active_data/version.rb +1 -1
  72. data/lib/active_data.rb +40 -17
  73. data/spec/lib/active_data/active_record/associations_spec.rb +107 -45
  74. data/spec/lib/active_data/active_record/nested_attributes_spec.rb +1 -2
  75. data/spec/lib/active_data/config_spec.rb +37 -15
  76. data/spec/lib/active_data/model/associations/embeds_many_spec.rb +475 -172
  77. data/spec/lib/active_data/model/associations/embeds_one_spec.rb +353 -96
  78. data/spec/lib/active_data/model/associations/nested_attributes_spec.rb +108 -12
  79. data/spec/lib/active_data/model/associations/persistence_adapters/active_record_spec.rb +58 -0
  80. data/spec/lib/active_data/model/associations/references_many_spec.rb +440 -64
  81. data/spec/lib/active_data/model/associations/references_one_spec.rb +347 -36
  82. data/spec/lib/active_data/model/associations/reflections/embeds_many_spec.rb +8 -7
  83. data/spec/lib/active_data/model/associations/reflections/embeds_one_spec.rb +7 -6
  84. data/spec/lib/active_data/model/associations/reflections/references_many_spec.rb +81 -33
  85. data/spec/lib/active_data/model/associations/reflections/references_one_spec.rb +116 -37
  86. data/spec/lib/active_data/model/associations/validations_spec.rb +27 -43
  87. data/spec/lib/active_data/model/associations_spec.rb +34 -25
  88. data/spec/lib/active_data/model/attributes/attribute_spec.rb +26 -23
  89. data/spec/lib/active_data/model/attributes/base_spec.rb +5 -6
  90. data/spec/lib/active_data/model/attributes/collection_spec.rb +7 -8
  91. data/spec/lib/active_data/model/attributes/dictionary_spec.rb +40 -33
  92. data/spec/lib/active_data/model/attributes/localized_spec.rb +27 -28
  93. data/spec/lib/active_data/model/attributes/reflections/attribute_spec.rb +6 -6
  94. data/spec/lib/active_data/model/attributes/represents_spec.rb +10 -78
  95. data/spec/lib/active_data/model/attributes_spec.rb +150 -45
  96. data/spec/lib/active_data/model/callbacks_spec.rb +69 -70
  97. data/spec/lib/active_data/model/conventions_spec.rb +0 -1
  98. data/spec/lib/active_data/model/dirty_spec.rb +22 -13
  99. data/spec/lib/active_data/model/lifecycle_spec.rb +49 -23
  100. data/spec/lib/active_data/model/persistence_spec.rb +5 -6
  101. data/spec/lib/active_data/model/representation_spec.rb +126 -0
  102. data/spec/lib/active_data/model/scopes_spec.rb +1 -3
  103. data/spec/lib/active_data/model/typecasting_spec.rb +6 -5
  104. data/spec/lib/active_data/model/validations/associated_spec.rb +26 -18
  105. data/spec/lib/active_data/model/validations/nested_spec.rb +89 -18
  106. data/spec/lib/active_data/model_spec.rb +1 -2
  107. data/spec/lib/active_data_spec.rb +0 -1
  108. data/spec/shared/nested_attribute_examples.rb +332 -0
  109. data/spec/spec_helper.rb +3 -0
  110. data/spec/support/model_helpers.rb +2 -2
  111. data/spec/support/muffle_helper.rb +7 -0
  112. metadata +52 -18
  113. data/lib/active_data/model/associations/collection/referenced.rb +0 -26
  114. data/lib/active_data/model/associations/reflections/reference_reflection.rb +0 -45
  115. 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::Associations::ReferencesMany do
@@ -6,13 +5,15 @@ describe ActiveData::Model::Associations::ReferencesMany do
6
5
  stub_model(:dummy)
7
6
  stub_class(:author, ActiveRecord::Base) do
8
7
  scope :name_starts_with_a, -> { where('name LIKE "a%"') }
8
+
9
+ validates :name, presence: true
9
10
  end
10
11
 
11
12
  stub_model(:book) do
12
13
  include ActiveData::Model::Persistence
13
14
  include ActiveData::Model::Associations
14
15
 
15
- attribute :title
16
+ attribute :title, String
16
17
  references_many :authors
17
18
  end
18
19
  end
@@ -31,6 +32,333 @@ describe ActiveData::Model::Associations::ReferencesMany do
31
32
  specify { expect(association).to eq(book.association(:authors)) }
32
33
  end
33
34
 
35
+ describe 'book#inspect' do
36
+ specify { expect(existing_book.inspect).to eq('#<Book authors: #<ReferencesMany [#<Author id: 1, name: "Rick">]>, title: "Genesis", author_ids: [1]>') }
37
+ end
38
+
39
+ describe '#build' do
40
+ specify { expect(association.build).to be_a Author }
41
+ specify { expect(association.build).not_to be_persisted }
42
+
43
+ specify do
44
+ expect { association.build(name: 'Morty') }
45
+ .to change { book.author_ids }
46
+ .from([]).to([nil])
47
+ end
48
+ specify do
49
+ expect { association.build(name: 'Morty') }
50
+ .to change { association.reader }.from([])
51
+ .to([an_instance_of(Author).and(have_attributes(name: 'Morty'))])
52
+ end
53
+
54
+ specify do
55
+ expect { existing_association.build(name: 'Morty') }
56
+ .to change { existing_book.author_ids }
57
+ .from([author.id]).to([author.id, nil])
58
+ end
59
+ specify do
60
+ expect { existing_association.build(name: 'Morty') }
61
+ .to change { existing_association.reader }.from([author])
62
+ .to([author, an_instance_of(Author).and(have_attributes(name: 'Morty'))])
63
+ end
64
+
65
+ context 'dirty' do
66
+ before do
67
+ Book.include ActiveData::Model::Dirty
68
+ end
69
+
70
+ specify do
71
+ expect { existing_association.build(name: 'Morty') }
72
+ .to change { existing_book.changes }
73
+ .from({}).to('author_ids' => [[author.id], [author.id, nil]])
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '#create' do
79
+ specify { expect(association.create).to be_a Author }
80
+ specify { expect(association.create).not_to be_persisted }
81
+
82
+ specify { expect(association.create(name: 'Morty')).to be_a Author }
83
+ specify { expect(association.create(name: 'Morty')).to be_persisted }
84
+
85
+ specify do
86
+ expect { association.create }
87
+ .to change { book.author_ids }
88
+ .from([]).to([nil])
89
+ end
90
+ specify do
91
+ expect { association.create }
92
+ .to change { association.target }
93
+ .from([]).to([an_instance_of(Author).and(be_new_record)])
94
+ end
95
+
96
+ specify do
97
+ expect { association.create(name: 'Morty') }
98
+ .to change { book.author_ids }
99
+ .from([]).to([be_a(Integer)])
100
+ end
101
+ specify do
102
+ expect { association.create(name: 'Morty') }
103
+ .to change { association.target }.from([])
104
+ .to([an_instance_of(Author)
105
+ .and(have_attributes(name: 'Morty'))
106
+ .and(be_persisted)])
107
+ end
108
+
109
+ specify do
110
+ expect { existing_association.create }
111
+ .to change { existing_book.author_ids }
112
+ .from([author.id]).to([author.id, nil])
113
+ end
114
+ specify do
115
+ expect { existing_association.create }
116
+ .to change { existing_association.reader }.from([author])
117
+ .to([author, an_instance_of(Author).and(be_new_record)])
118
+ end
119
+
120
+ specify do
121
+ expect { existing_association.create(name: 'Morty') }
122
+ .to change { existing_book.author_ids }
123
+ .from([author.id]).to([author.id, be_a(Integer)])
124
+ end
125
+ specify do
126
+ expect { existing_association.create(name: 'Morty') }
127
+ .to change { existing_association.reader }.from([author])
128
+ .to([author, an_instance_of(Author)
129
+ .and(have_attributes(name: 'Morty'))
130
+ .and(be_persisted)])
131
+ end
132
+
133
+ context 'dirty' do
134
+ before do
135
+ Book.include ActiveData::Model::Dirty
136
+ end
137
+
138
+ specify do
139
+ expect { existing_association.create(name: 'Morty') }
140
+ .to change { existing_book.changes }
141
+ .from({}).to('author_ids' => [[author.id], [author.id, be_a(Integer)]])
142
+ end
143
+ end
144
+ end
145
+
146
+ describe '#create!' do
147
+ specify { expect { association.create! }.to raise_error ActiveRecord::RecordInvalid }
148
+
149
+ specify { expect(association.create!(name: 'Morty')).to be_a Author }
150
+ specify { expect(association.create!(name: 'Morty')).to be_persisted }
151
+
152
+ specify do
153
+ expect { muffle(ActiveRecord::RecordInvalid) { association.create! } }
154
+ .to change { book.author_ids }
155
+ .from([]).to([nil])
156
+ end
157
+ specify do
158
+ expect { muffle(ActiveRecord::RecordInvalid) { association.create! } }
159
+ .to change { association.target }
160
+ .from([]).to([an_instance_of(Author).and(be_new_record)])
161
+ end
162
+
163
+ specify do
164
+ expect { association.create!(name: 'Morty') }
165
+ .to change { book.author_ids }
166
+ .from([]).to([be_a(Integer)])
167
+ end
168
+ specify do
169
+ expect { association.create!(name: 'Morty') }
170
+ .to change { association.target }.from([])
171
+ .to([an_instance_of(Author)
172
+ .and(have_attributes(name: 'Morty'))
173
+ .and(be_persisted)])
174
+ end
175
+
176
+ specify do
177
+ expect { muffle(ActiveRecord::RecordInvalid) { existing_association.create! } }
178
+ .to change { existing_book.author_ids }
179
+ .from([author.id]).to([author.id, nil])
180
+ end
181
+ specify do
182
+ expect { muffle(ActiveRecord::RecordInvalid) { existing_association.create! } }
183
+ .to change { existing_association.reader }.from([author])
184
+ .to([author, an_instance_of(Author).and(be_new_record)])
185
+ end
186
+
187
+ specify do
188
+ expect { existing_association.create!(name: 'Morty') }
189
+ .to change { existing_book.author_ids }
190
+ .from([author.id]).to([author.id, be_a(Integer)])
191
+ end
192
+ specify do
193
+ expect { existing_association.create!(name: 'Morty') }
194
+ .to change { existing_association.reader }.from([author])
195
+ .to([author, an_instance_of(Author)
196
+ .and(have_attributes(name: 'Morty'))
197
+ .and(be_persisted)])
198
+ end
199
+ end
200
+
201
+ describe '#apply_changes' do
202
+ specify do
203
+ association.build
204
+ expect(association.apply_changes).to eq(false)
205
+ end
206
+ specify do
207
+ association.build
208
+ expect { association.apply_changes }
209
+ .not_to change { association.target.map(&:persisted?) }
210
+ .from([false])
211
+ end
212
+ specify do
213
+ association.build(name: 'Rick')
214
+ expect(association.apply_changes).to eq(true)
215
+ end
216
+ specify do
217
+ association.build(name: 'Rick')
218
+ expect { association.apply_changes }
219
+ .to change { association.target.map(&:persisted?) }
220
+ .from([false]).to([true])
221
+ end
222
+ specify do
223
+ association.build(name: 'Rick')
224
+ expect { association.apply_changes }
225
+ .to change { book.author_ids }
226
+ .from([nil]).to([be_a(Integer)])
227
+ end
228
+ specify do
229
+ existing_association.target.first.name = 'Morty'
230
+ expect { existing_association.apply_changes }
231
+ .not_to change { author.reload.name }
232
+ end
233
+ specify do
234
+ existing_association.target.first.mark_for_destruction
235
+ existing_association.build(name: 'Morty')
236
+ expect { existing_association.apply_changes }
237
+ .to change { existing_book.author_ids }
238
+ .from([author.id, nil]).to([author.id, be_a(Integer)])
239
+ end
240
+ specify do
241
+ existing_association.target.first.mark_for_destruction
242
+ existing_association.build(name: 'Morty')
243
+ expect { existing_association.apply_changes }
244
+ .to change { existing_association.target.map(&:persisted?) }
245
+ .from([true, false]).to([true, true])
246
+ end
247
+ specify do
248
+ existing_association.target.first.destroy!
249
+ existing_association.build(name: 'Morty')
250
+ expect { existing_association.apply_changes }
251
+ .to change { existing_book.author_ids }
252
+ .from([author.id, nil]).to([author.id, be_a(Integer)])
253
+ end
254
+ specify do
255
+ existing_association.target.first.destroy!
256
+ existing_association.build(name: 'Morty')
257
+ expect { existing_association.apply_changes }
258
+ .to change { existing_association.target.map(&:persisted?) }
259
+ .from([false, false]).to([false, true])
260
+ end
261
+
262
+ context ':autosave' do
263
+ before do
264
+ Book.references_many :authors, autosave: true
265
+ end
266
+
267
+ specify do
268
+ association.build
269
+ expect(association.apply_changes).to eq(false)
270
+ end
271
+ specify do
272
+ association.build
273
+ expect { association.apply_changes }
274
+ .not_to change { association.target.map(&:persisted?) }
275
+ .from([false])
276
+ end
277
+ specify do
278
+ association.build(name: 'Rick')
279
+ expect(association.apply_changes).to eq(true)
280
+ end
281
+ specify do
282
+ association.build(name: 'Rick')
283
+ expect { association.apply_changes }
284
+ .to change { association.target.map(&:persisted?) }
285
+ .from([false]).to([true])
286
+ end
287
+ specify do
288
+ association.build(name: 'Rick')
289
+ expect { association.apply_changes }
290
+ .to change { book.author_ids }
291
+ .from([nil]).to([be_a(Integer)])
292
+ end
293
+ specify do
294
+ existing_association.target.first.name = 'Morty'
295
+ expect { existing_association.apply_changes }
296
+ .to change { author.reload.name }
297
+ .from('Rick').to('Morty')
298
+ end
299
+ specify do
300
+ existing_association.target.first.mark_for_destruction
301
+ existing_association.build(name: 'Morty')
302
+ expect { existing_association.apply_changes }
303
+ .to change { existing_book.author_ids }
304
+ .from([author.id, nil]).to([author.id, be_a(Integer)])
305
+ end
306
+ specify do
307
+ existing_association.target.first.mark_for_destruction
308
+ existing_association.build(name: 'Morty')
309
+ expect { existing_association.apply_changes }
310
+ .to change { existing_association.target.map(&:persisted?) }
311
+ .from([true, false]).to([false, true])
312
+ end
313
+ specify do
314
+ existing_association.target.first.destroy!
315
+ existing_association.build(name: 'Morty')
316
+ expect { existing_association.apply_changes }
317
+ .to change { existing_book.author_ids }
318
+ .from([author.id, nil]).to([author.id, be_a(Integer)])
319
+ end
320
+ specify do
321
+ existing_association.target.first.destroy!
322
+ existing_association.build(name: 'Morty')
323
+ expect { existing_association.apply_changes }
324
+ .to change { existing_association.target.map(&:persisted?) }
325
+ .from([false, false]).to([false, true])
326
+ end
327
+ end
328
+ end
329
+
330
+ describe '#apply_changes!' do
331
+ specify do
332
+ association.build
333
+ expect { association.apply_changes! }
334
+ .to raise_error(ActiveData::AssociationChangesNotApplied)
335
+ end
336
+ specify do
337
+ association.build
338
+ expect { muffle(ActiveData::AssociationChangesNotApplied) { association.apply_changes! } }
339
+ .not_to change { association.target.map(&:persisted?) }
340
+ .from([false])
341
+ end
342
+
343
+ context ':autosave' do
344
+ before do
345
+ Book.references_many :authors, autosave: true
346
+ end
347
+
348
+ specify do
349
+ association.build
350
+ expect { association.apply_changes! }
351
+ .to raise_error(ActiveData::AssociationChangesNotApplied)
352
+ end
353
+ specify do
354
+ association.build
355
+ expect { muffle(ActiveData::AssociationChangesNotApplied) { association.apply_changes! } }
356
+ .not_to change { association.target.map(&:persisted?) }
357
+ .from([false])
358
+ end
359
+ end
360
+ end
361
+
34
362
  describe '#scope' do
35
363
  specify { expect(association.scope).to be_a ActiveRecord::Relation }
36
364
  specify { expect(association.scope).to respond_to(:where) }
@@ -44,7 +372,7 @@ describe ActiveData::Model::Associations::ReferencesMany do
44
372
  end
45
373
 
46
374
  describe '#default' do
47
- before { Book.references_many :authors, default: ->(book) { author.id } }
375
+ before { Book.references_many :authors, default: ->(_book) { author.id } }
48
376
  let(:existing_book) { Book.instantiate title: 'Genesis' }
49
377
 
50
378
  specify { expect(association.target).to eq([author]) }
@@ -70,15 +398,17 @@ describe ActiveData::Model::Associations::ReferencesMany do
70
398
 
71
399
  context do
72
400
  before { existing_association.reader.last.name = 'Conan' }
73
- specify { expect { existing_association.reload }
74
- .to change { existing_association.reader.map(&:name) }
75
- .from(['Conan']).to(['Rick']) }
401
+ specify do
402
+ expect { existing_association.reload }
403
+ .to change { existing_association.reader.map(&:name) }
404
+ .from(['Conan']).to(['Rick'])
405
+ end
76
406
  end
77
407
  end
78
408
 
79
409
  describe '#reader' do
80
410
  specify { expect(association.reader).to eq([]) }
81
- specify { expect(association.reader).to be_a ActiveData::Model::Associations::Collection::Referenced }
411
+ specify { expect(association.reader).to be_a ActiveData::Model::Associations::PersistenceAdapters::ActiveRecord::ReferencedProxy }
82
412
 
83
413
  specify { expect(existing_association.reader.first).to be_a Author }
84
414
  specify { expect(existing_association.reader.first).to be_persisted }
@@ -109,60 +439,90 @@ describe ActiveData::Model::Associations::ReferencesMany do
109
439
  let(:new_author2) { Author.create!(name: 'Adam') }
110
440
  let(:new_author3) { Author.new(name: 'Jane') }
111
441
 
112
- specify { expect { association.writer([Dummy.new]) }
113
- .to raise_error ActiveData::AssociationTypeMismatch }
442
+ specify do
443
+ expect { association.writer([Dummy.new]) }
444
+ .to raise_error ActiveData::AssociationTypeMismatch
445
+ end
114
446
 
115
447
  specify { expect { association.writer(nil) }.to raise_error NoMethodError }
116
448
  specify { expect { association.writer(new_author1) }.to raise_error NoMethodError }
117
449
  specify { expect(association.writer([])).to eq([]) }
118
450
 
119
451
  specify { expect(association.writer([new_author1])).to eq([new_author1]) }
120
- specify { expect { association.writer([new_author1]) }
121
- .to change { association.reader.map(&:name) }.from([]).to(['John']) }
122
- specify { expect { association.writer([new_author1]) }
123
- .to change { book.read_attribute(:author_ids) }
124
- .from([]).to([new_author1.id]) }
125
-
126
- specify { expect { existing_association.writer([new_author1, Dummy.new, new_author2]) }
127
- .to raise_error ActiveData::AssociationTypeMismatch }
128
- specify { expect { existing_association.writer([new_author1, Dummy.new, new_author2]) rescue nil }
129
- .not_to change { existing_book.read_attribute(:author_ids) } }
130
- specify { expect { existing_association.writer([new_author1, Dummy.new, new_author2]) rescue nil }
131
- .not_to change { existing_association.reader } }
452
+ specify do
453
+ expect { association.writer([new_author1]) }
454
+ .to change { association.reader.map(&:name) }.from([]).to(['John'])
455
+ end
456
+ specify do
457
+ expect { association.writer([new_author1]) }
458
+ .to change { book.read_attribute(:author_ids) }
459
+ .from([]).to([new_author1.id])
460
+ end
461
+
462
+ specify do
463
+ expect { existing_association.writer([new_author1, Dummy.new, new_author2]) }
464
+ .to raise_error ActiveData::AssociationTypeMismatch
465
+ end
466
+ specify do
467
+ expect { muffle(ActiveData::AssociationTypeMismatch) { existing_association.writer([new_author1, Dummy.new, new_author2]) } }
468
+ .not_to change { existing_book.read_attribute(:author_ids) }
469
+ end
470
+ specify do
471
+ expect { muffle(ActiveData::AssociationTypeMismatch) { existing_association.writer([new_author1, Dummy.new, new_author2]) } }
472
+ .not_to change { existing_association.reader }
473
+ end
132
474
 
133
475
  specify { expect { existing_association.writer(nil) }.to raise_error NoMethodError }
134
- specify { expect { existing_association.writer(nil) rescue nil }
135
- .not_to change { existing_book.read_attribute(:author_ids) } }
136
- specify { expect { existing_association.writer(nil) rescue nil }
137
- .not_to change { existing_association.reader } }
476
+ specify do
477
+ expect { muffle(NoMethodError) { existing_association.writer(nil) } }
478
+ .not_to change { existing_book.read_attribute(:author_ids) }
479
+ end
480
+ specify do
481
+ expect { muffle(NoMethodError) { existing_association.writer(nil) } }
482
+ .not_to change { existing_association.reader }
483
+ end
138
484
 
139
485
  specify { expect(existing_association.writer([])).to eq([]) }
140
- specify { expect { existing_association.writer([]) }
141
- .to change { existing_book.read_attribute(:author_ids) }.to([]) }
142
- specify { expect { existing_association.writer([]) }
143
- .to change { existing_association.reader }.from([author]).to([]) }
486
+ specify do
487
+ expect { existing_association.writer([]) }
488
+ .to change { existing_book.read_attribute(:author_ids) }.to([])
489
+ end
490
+ specify do
491
+ expect { existing_association.writer([]) }
492
+ .to change { existing_association.reader }.from([author]).to([])
493
+ end
144
494
 
145
495
  specify { expect(existing_association.writer([new_author1, new_author2])).to eq([new_author1, new_author2]) }
146
- specify { expect { existing_association.writer([new_author1, new_author2]) }
147
- .to change { existing_association.reader.map(&:name) }
148
- .from(['Rick']).to(['John', 'Adam']) }
149
- specify { expect { existing_association.writer([new_author1, new_author2]) }
150
- .to change { existing_book.read_attribute(:author_ids) }
151
- .from([author.id]).to([new_author1.id, new_author2.id]) }
496
+ specify do
497
+ expect { existing_association.writer([new_author1, new_author2]) }
498
+ .to change { existing_association.reader.map(&:name) }
499
+ .from(['Rick']).to(%w[John Adam])
500
+ end
501
+ specify do
502
+ expect { existing_association.writer([new_author1, new_author2]) }
503
+ .to change { existing_book.read_attribute(:author_ids) }
504
+ .from([author.id]).to([new_author1.id, new_author2.id])
505
+ end
152
506
 
153
- specify { expect { existing_association.writer([new_author3]) }
154
- .to change { existing_association.target }.from([author]).to([new_author3]) }
155
- specify { expect { existing_association.writer([new_author3]) }
156
- .to change { existing_book.read_attribute(:author_ids) }
157
- .from([author.id]).to([nil]) }
507
+ specify do
508
+ expect { existing_association.writer([new_author3]) }
509
+ .to change { existing_association.target }.from([author]).to([new_author3])
510
+ end
511
+ specify do
512
+ expect { existing_association.writer([new_author3]) }
513
+ .to change { existing_book.read_attribute(:author_ids) }
514
+ .from([author.id]).to([nil])
515
+ end
158
516
  end
159
517
 
160
518
  describe '#concat' do
161
519
  let(:new_author1) { Author.create!(name: 'John') }
162
520
  let(:new_author2) { Author.create!(name: 'Adam') }
163
521
 
164
- specify { expect { association.concat(Dummy.new) }
165
- .to raise_error ActiveData::AssociationTypeMismatch }
522
+ specify do
523
+ expect { association.concat(Dummy.new) }
524
+ .to raise_error ActiveData::AssociationTypeMismatch
525
+ end
166
526
 
167
527
  specify { expect { association.concat(nil) }.to raise_error ActiveData::AssociationTypeMismatch }
168
528
  specify { expect(association.concat([])).to eq([]) }
@@ -170,27 +530,43 @@ describe ActiveData::Model::Associations::ReferencesMany do
170
530
  specify { expect(existing_association.concat).to eq(existing_book.authors) }
171
531
 
172
532
  specify { expect(association.concat(new_author1)).to eq([new_author1]) }
173
- specify { expect { association.concat(new_author1) }
174
- .to change { association.reader.map(&:name) }.from([]).to(['John']) }
175
- specify { expect { association.concat(new_author1) }
176
- .to change { book.read_attribute(:author_ids) }.from([]).to([1]) }
177
-
178
- specify { expect { existing_association.concat(new_author1, Dummy.new, new_author2) }
179
- .to raise_error ActiveData::AssociationTypeMismatch }
180
- specify { expect { existing_association.concat(new_author1, Dummy.new, new_author2) rescue nil }
181
- .to change { existing_book.read_attribute(:author_ids) }
182
- .from([author.id]).to([author.id, new_author1.id]) }
183
- specify { expect { existing_association.concat(new_author1, Dummy.new, new_author2) rescue nil }
184
- .to change { existing_association.reader.map(&:name) }
185
- .from(['Rick']).to(['Rick', 'John']) }
186
-
187
- specify { expect(existing_association.concat(new_author1, new_author2))
188
- .to eq([author, new_author1, new_author2]) }
189
- specify { expect { existing_association.concat([new_author1, new_author2]) }
190
- .to change { existing_association.reader.map(&:name) }
191
- .from(['Rick']).to(['Rick', 'John', 'Adam']) }
192
- specify { expect { existing_association.concat([new_author1, new_author2]) }
193
- .to change { existing_book.read_attribute(:author_ids) }
194
- .from([author.id]).to([author.id, new_author1.id, new_author2.id]) }
533
+ specify do
534
+ expect { association.concat(new_author1) }
535
+ .to change { association.reader.map(&:name) }.from([]).to(['John'])
536
+ end
537
+ specify do
538
+ expect { association.concat(new_author1) }
539
+ .to change { book.read_attribute(:author_ids) }.from([]).to([1])
540
+ end
541
+
542
+ specify do
543
+ expect { existing_association.concat(new_author1, Dummy.new, new_author2) }
544
+ .to raise_error ActiveData::AssociationTypeMismatch
545
+ end
546
+ specify do
547
+ expect { muffle(ActiveData::AssociationTypeMismatch) { existing_association.concat(new_author1, Dummy.new, new_author2) } }
548
+ .to change { existing_book.read_attribute(:author_ids) }
549
+ .from([author.id]).to([author.id, new_author1.id])
550
+ end
551
+ specify do
552
+ expect { muffle(ActiveData::AssociationTypeMismatch) { existing_association.concat(new_author1, Dummy.new, new_author2) } }
553
+ .to change { existing_association.reader.map(&:name) }
554
+ .from(['Rick']).to(%w[Rick John])
555
+ end
556
+
557
+ specify do
558
+ expect(existing_association.concat(new_author1, new_author2))
559
+ .to eq([author, new_author1, new_author2])
560
+ end
561
+ specify do
562
+ expect { existing_association.concat([new_author1, new_author2]) }
563
+ .to change { existing_association.reader.map(&:name) }
564
+ .from(['Rick']).to(%w[Rick John Adam])
565
+ end
566
+ specify do
567
+ expect { existing_association.concat([new_author1, new_author2]) }
568
+ .to change { existing_book.read_attribute(:author_ids) }
569
+ .from([author.id]).to([author.id, new_author1.id, new_author2.id])
570
+ end
195
571
  end
196
572
  end