granite-form 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -2
  3. data/.github/workflows/{ci.yml → ruby.yml} +22 -4
  4. data/.rubocop.yml +1 -1
  5. data/.rubocop_todo.yml +3 -3
  6. data/Appraisals +1 -2
  7. data/CHANGELOG.md +7 -0
  8. data/README.md +0 -2
  9. data/docker-compose.yml +14 -0
  10. data/gemfiles/rails.5.0.gemfile +0 -1
  11. data/gemfiles/rails.5.1.gemfile +0 -1
  12. data/gemfiles/rails.5.2.gemfile +0 -1
  13. data/granite-form.gemspec +15 -15
  14. data/lib/granite/form/active_record/associations.rb +1 -1
  15. data/lib/granite/form/base.rb +1 -2
  16. data/lib/granite/form/errors.rb +0 -15
  17. data/lib/granite/form/model/associations/base.rb +0 -4
  18. data/lib/granite/form/model/associations/collection/embedded.rb +2 -1
  19. data/lib/granite/form/model/associations/collection/proxy.rb +1 -1
  20. data/lib/granite/form/model/associations/embeds_any.rb +7 -0
  21. data/lib/granite/form/model/associations/embeds_many.rb +9 -58
  22. data/lib/granite/form/model/associations/embeds_one.rb +7 -36
  23. data/lib/granite/form/model/associations/nested_attributes.rb +5 -5
  24. data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +0 -4
  25. data/lib/granite/form/model/associations/persistence_adapters/base.rb +0 -4
  26. data/lib/granite/form/model/associations/references_many.rb +0 -32
  27. data/lib/granite/form/model/associations/references_one.rb +0 -28
  28. data/lib/granite/form/model/associations/reflections/embeds_any.rb +1 -1
  29. data/lib/granite/form/model/associations/reflections/references_any.rb +0 -4
  30. data/lib/granite/form/model/associations/reflections/references_one.rb +0 -2
  31. data/lib/granite/form/model/associations/reflections/singular.rb +0 -8
  32. data/lib/granite/form/model/associations.rb +0 -6
  33. data/lib/granite/form/model/attributes/base.rb +1 -1
  34. data/lib/granite/form/model/attributes/reflections/attribute.rb +0 -6
  35. data/lib/granite/form/model/attributes/reflections/base.rb +8 -7
  36. data/lib/granite/form/model/attributes/reflections/reference_one.rb +0 -6
  37. data/lib/granite/form/model/persistence.rb +1 -19
  38. data/lib/granite/form/model.rb +0 -2
  39. data/lib/granite/form/version.rb +1 -1
  40. data/spec/granite/form/active_record/associations_spec.rb +16 -18
  41. data/spec/granite/form/model/associations/embeds_many_spec.rb +29 -305
  42. data/spec/granite/form/model/associations/embeds_one_spec.rb +27 -212
  43. data/spec/granite/form/model/associations/nested_attributes_spec.rb +0 -95
  44. data/spec/granite/form/model/associations/references_many_spec.rb +5 -326
  45. data/spec/granite/form/model/associations/references_one_spec.rb +6 -278
  46. data/spec/granite/form/model/associations/reflections/embeds_any_spec.rb +1 -2
  47. data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +18 -26
  48. data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +16 -23
  49. data/spec/granite/form/model/associations/reflections/references_many_spec.rb +1 -1
  50. data/spec/granite/form/model/associations/reflections/references_one_spec.rb +1 -22
  51. data/spec/granite/form/model/associations/validations_spec.rb +0 -3
  52. data/spec/granite/form/model/associations_spec.rb +3 -24
  53. data/spec/granite/form/model/dirty_spec.rb +1 -1
  54. data/spec/granite/form/model/persistence_spec.rb +0 -2
  55. data/spec/granite/form/model/validations/associated_spec.rb +2 -4
  56. data/spec/granite/form/model/validations/nested_spec.rb +2 -4
  57. data/spec/spec_helper.rb +0 -15
  58. data/spec/support/active_record.rb +20 -0
  59. data/spec/support/shared/nested_attribute_examples.rb +3 -21
  60. metadata +32 -38
  61. data/.github/workflows/main.yml +0 -29
  62. data/gemfiles/rails.4.2.gemfile +0 -15
  63. data/lib/granite/form/model/callbacks.rb +0 -72
  64. data/lib/granite/form/model/lifecycle.rb +0 -309
  65. data/spec/granite/form/model/callbacks_spec.rb +0 -337
  66. data/spec/granite/form/model/lifecycle_spec.rb +0 -356
@@ -3,7 +3,8 @@ require 'spec_helper'
3
3
  describe Granite::Form::Model::Associations::EmbedsOne do
4
4
  before do
5
5
  stub_model(:author) do
6
- include Granite::Form::Model::Lifecycle
6
+ include Granite::Form::Model::Persistence
7
+ include Granite::Form::Model::Associations
7
8
 
8
9
  attribute :name, String
9
10
  validates :name, presence: true
@@ -61,12 +62,6 @@ describe Granite::Form::Model::Associations::EmbedsOne do
61
62
  ])
62
63
  end
63
64
 
64
- specify do
65
- expect { association.create(name: 'Author1') }
66
- .to change { book.callbacks }
67
- .to([[:before_add, author1], [:after_add, author1]])
68
- end
69
-
70
65
  specify do
71
66
  expect { association.writer(author1) }
72
67
  .to change { book.callbacks }
@@ -118,7 +113,6 @@ describe Granite::Form::Model::Associations::EmbedsOne do
118
113
  let(:author) { Author.new(name: 'Author') }
119
114
 
120
115
  specify { expect(association.build.embedder).to eq(book) }
121
- specify { expect(association.create.embedder).to eq(book) }
122
116
  specify do
123
117
  expect { association.writer(author) }
124
118
  .to change { author.embedder }.from(nil).to(book)
@@ -156,7 +150,6 @@ describe Granite::Form::Model::Associations::EmbedsOne do
156
150
  end
157
151
 
158
152
  specify { expect(association.build(name: 'Author').name).to eq('AuthorBook') }
159
- specify { expect(association.create(name: 'Author').name).to eq('AuthorBook') }
160
153
  end
161
154
  end
162
155
 
@@ -175,132 +168,6 @@ describe Granite::Form::Model::Associations::EmbedsOne do
175
168
  end
176
169
  end
177
170
 
178
- describe '#create' do
179
- specify { expect(association.create).to be_a Author }
180
- specify { expect(association.create).not_to be_persisted }
181
-
182
- specify { expect(association.create(name: 'Fred')).to be_a Author }
183
- specify { expect(association.create(name: 'Fred')).to be_persisted }
184
-
185
- specify do
186
- expect { association.create }
187
- .not_to change { book.read_attribute(:author) }
188
- end
189
- specify do
190
- expect { association.create(name: 'Fred') }
191
- .to change { book.read_attribute(:author) }
192
- .from(nil).to('name' => 'Fred')
193
- end
194
-
195
- specify do
196
- expect { existing_association.create }
197
- .not_to change { existing_book.read_attribute(:author) }
198
- end
199
- specify do
200
- expect { existing_association.create(name: 'Fred') }
201
- .to change { existing_book.read_attribute(:author) }
202
- .from('name' => 'Johny').to('name' => 'Fred')
203
- end
204
- end
205
-
206
- describe '#create!' do
207
- specify { expect { association.create! }.to raise_error Granite::Form::ValidationError }
208
- specify do
209
- expect { muffle(Granite::Form::ValidationError) { association.create! } }
210
- .to change { association.target }
211
- .from(nil).to(an_instance_of(Author))
212
- end
213
-
214
- specify { expect(association.create!(name: 'Fred')).to be_a Author }
215
- specify { expect(association.create!(name: 'Fred')).to be_persisted }
216
-
217
- specify do
218
- expect { muffle(Granite::Form::ValidationError) { association.create! } }
219
- .not_to change { book.read_attribute(:author) }
220
- end
221
- specify do
222
- expect { muffle(Granite::Form::ValidationError) { association.create! } }
223
- .to change { association.reader.try(:attributes) }
224
- .from(nil).to('name' => nil)
225
- end
226
- specify do
227
- expect { association.create(name: 'Fred') }
228
- .to change { book.read_attribute(:author) }
229
- .from(nil).to('name' => 'Fred')
230
- end
231
-
232
- specify do
233
- expect { muffle(Granite::Form::ValidationError) { existing_association.create! } }
234
- .not_to change { existing_book.read_attribute(:author) }
235
- end
236
- specify do
237
- expect { muffle(Granite::Form::ValidationError) { existing_association.create! } }
238
- .to change { existing_association.reader.try(:attributes) }
239
- .from('name' => 'Johny').to('name' => nil)
240
- end
241
- specify do
242
- expect { existing_association.create!(name: 'Fred') }
243
- .to change { existing_book.read_attribute(:author) }
244
- .from('name' => 'Johny').to('name' => 'Fred')
245
- end
246
- end
247
-
248
- describe '#apply_changes' do
249
- specify do
250
- association.build
251
- expect { association.apply_changes }
252
- .not_to change { association.target.persisted? }.from(false)
253
- end
254
- specify do
255
- association.build(name: 'Fred')
256
- expect { association.apply_changes }
257
- .to change { association.target.persisted? }.to(true)
258
- end
259
- specify do
260
- existing_association.target.mark_for_destruction
261
- expect { existing_association.apply_changes }
262
- .to change { existing_association.target }.to(nil)
263
- end
264
- specify do
265
- existing_association.target.destroy!
266
- expect { existing_association.apply_changes }
267
- .to change { existing_association.target }.to(nil)
268
- end
269
- specify do
270
- existing_association.target.mark_for_destruction
271
- expect { existing_association.apply_changes }
272
- .to change { existing_association.destroyed.try(:name) }.from(nil).to('Johny')
273
- end
274
- specify do
275
- existing_association.target.destroy!
276
- expect { existing_association.apply_changes }
277
- .to change { existing_association.destroyed.try(:name) }.from(nil).to('Johny')
278
- end
279
- end
280
-
281
- describe '#apply_changes!' do
282
- specify do
283
- association.build
284
- expect { association.apply_changes! }
285
- .to raise_error Granite::Form::AssociationChangesNotApplied
286
- end
287
- specify do
288
- association.build(name: 'Fred')
289
- expect { association.apply_changes! }
290
- .to change { association.target.persisted? }.to(true)
291
- end
292
- specify do
293
- existing_association.target.mark_for_destruction
294
- expect { existing_association.apply_changes! }
295
- .to change { existing_association.target }.to(nil)
296
- end
297
- specify do
298
- existing_association.target.destroy!
299
- expect { existing_association.apply_changes! }
300
- .to change { existing_association.target }.to(nil)
301
- end
302
- end
303
-
304
171
  describe '#target' do
305
172
  specify { expect(association.target).to be_nil }
306
173
  specify { expect(existing_association.target).to eq(existing_book.author) }
@@ -369,6 +236,31 @@ describe Granite::Form::Model::Associations::EmbedsOne do
369
236
  end
370
237
  end
371
238
 
239
+ describe '#sync' do
240
+ let!(:author) { association.build(name: 'Fred') }
241
+
242
+ specify { expect { association.sync }.to change { book.read_attribute(:author) }.from(nil).to('name' => 'Fred') }
243
+
244
+ context 'when embedding is nested' do
245
+ before do
246
+ Author.class_eval do
247
+ include Granite::Form::Model::Associations
248
+
249
+ embeds_many :reviews do
250
+ attribute :rating, Integer
251
+ end
252
+ end
253
+
254
+ author.reviews.build(rating: 7)
255
+ end
256
+
257
+ specify do
258
+ expect { association.sync }.to change { book.read_attribute(:author) }
259
+ .from(nil).to('name' => 'Fred', 'reviews' => [{'rating' => 7}])
260
+ end
261
+ end
262
+ end
263
+
372
264
  describe '#clear' do
373
265
  specify { expect(association.clear).to eq(true) }
374
266
  specify { expect { association.clear }.not_to change { association.reader } }
@@ -378,28 +270,6 @@ describe Granite::Form::Model::Associations::EmbedsOne do
378
270
  expect { existing_association.clear }
379
271
  .to change { existing_association.reader.try(:attributes) }.from('name' => 'Johny').to(nil)
380
272
  end
381
- specify do
382
- expect { existing_association.clear }
383
- .to change { existing_book.read_attribute(:author) }.from('name' => 'Johny').to(nil)
384
- end
385
-
386
- context do
387
- before { Author.send(:include, Granite::Form::Model::Callbacks) }
388
- if ActiveModel.version >= Gem::Version.new('5.0.0')
389
- before { Author.before_destroy { throw :abort } }
390
- else
391
- before { Author.before_destroy { false } }
392
- end
393
- specify { expect(existing_association.clear).to eq(false) }
394
- specify do
395
- expect { existing_association.clear }
396
- .not_to change { existing_association.reader }
397
- end
398
- specify do
399
- expect { existing_association.clear }
400
- .not_to change { existing_book.read_attribute(:author).symbolize_keys }
401
- end
402
- end
403
273
  end
404
274
 
405
275
  describe '#reader' do
@@ -441,23 +311,6 @@ describe Granite::Form::Model::Associations::EmbedsOne do
441
311
  expect { association.writer(new_author) }
442
312
  .to change { association.reader.try(:attributes) }.from(nil).to('name' => 'Morty')
443
313
  end
444
- specify do
445
- expect { association.writer(new_author) }
446
- .to change { book.read_attribute(:author) }.from(nil).to('name' => 'Morty')
447
- end
448
-
449
- specify do
450
- expect { association.writer(invalid_author) }
451
- .to raise_error Granite::Form::AssociationChangesNotApplied
452
- end
453
- specify do
454
- expect { muffle(Granite::Form::AssociationChangesNotApplied) { association.writer(invalid_author) } }
455
- .not_to change { association.reader }
456
- end
457
- specify do
458
- expect { muffle(Granite::Form::AssociationChangesNotApplied) { association.writer(invalid_author) } }
459
- .not_to change { book.read_attribute(:author) }
460
- end
461
314
  end
462
315
 
463
316
  context 'persisted owner' do
@@ -468,32 +321,16 @@ describe Granite::Form::Model::Associations::EmbedsOne do
468
321
 
469
322
  specify { expect(association.writer(nil)).to be_nil }
470
323
  specify { expect(association.writer(new_author)).to eq(new_author) }
471
- specify do
472
- expect { association.writer(nil) }
473
- .not_to change { book.read_attribute(:author) }
474
- end
475
324
  specify do
476
325
  expect { association.writer(new_author) }
477
326
  .to change { association.reader.try(:attributes) }.from(nil).to('name' => 'Morty')
478
327
  end
479
- specify do
480
- expect { association.writer(new_author) }
481
- .not_to change { book.read_attribute(:author) }
482
- end
483
328
 
484
329
  specify do
485
330
  expect { association.writer(invalid_author) }
486
331
  .to change { association.reader.try(:attributes) }.from(nil).to('name' => nil)
487
332
  end
488
- specify do
489
- expect { association.writer(invalid_author) }
490
- .not_to change { book.read_attribute(:author) }
491
- end
492
333
 
493
- specify do
494
- expect { muffle(Granite::Form::AssociationTypeMismatch) { existing_association.writer(stub_model(:dummy).new) } }
495
- .not_to change { existing_book.read_attribute(:author) }
496
- end
497
334
  specify do
498
335
  expect { muffle(Granite::Form::AssociationTypeMismatch) { existing_association.writer(stub_model(:dummy).new) } }
499
336
  .not_to change { existing_association.reader }
@@ -501,33 +338,11 @@ describe Granite::Form::Model::Associations::EmbedsOne do
501
338
 
502
339
  specify { expect(existing_association.writer(nil)).to be_nil }
503
340
  specify { expect(existing_association.writer(new_author)).to eq(new_author) }
504
- specify do
505
- expect { existing_association.writer(nil) }
506
- .to change { existing_book.read_attribute(:author) }.from('name' => 'Johny').to(nil)
507
- end
508
341
  specify do
509
342
  expect { existing_association.writer(new_author) }
510
343
  .to change { existing_association.reader.try(:attributes) }
511
344
  .from('name' => 'Johny').to('name' => 'Morty')
512
345
  end
513
- specify do
514
- expect { existing_association.writer(new_author) }
515
- .to change { existing_book.read_attribute(:author) }
516
- .from('name' => 'Johny').to('name' => 'Morty')
517
- end
518
-
519
- specify do
520
- expect { existing_association.writer(invalid_author) }
521
- .to raise_error Granite::Form::AssociationChangesNotApplied
522
- end
523
- specify do
524
- expect { muffle(Granite::Form::AssociationChangesNotApplied) { existing_association.writer(invalid_author) } }
525
- .not_to change { existing_association.reader }
526
- end
527
- specify do
528
- expect { muffle(Granite::Form::AssociationChangesNotApplied) { existing_association.writer(invalid_author) } }
529
- .not_to change { existing_book.read_attribute(:author) }
530
- end
531
346
  end
532
347
  end
533
348
  end
@@ -11,107 +11,12 @@ describe Granite::Form::Model::Associations::NestedAttributes do
11
11
  embeds_many :projects
12
12
 
13
13
  accepts_nested_attributes_for :profile, :projects
14
-
15
- def save
16
- apply_association_changes!
17
- end
18
14
  end
19
15
  end
20
16
 
21
17
  include_examples 'nested attributes'
22
18
  end
23
19
 
24
- xcontext 'references_one' do
25
- before do
26
- stub_class(:author, ActiveRecord::Base)
27
- stub_class(:user, ActiveRecord::Base)
28
-
29
- stub_model :book do
30
- include Granite::Form::Model::Associations
31
-
32
- references_one :author
33
- references_many :users
34
-
35
- accepts_nested_attributes_for :author, :users
36
- end
37
- end
38
-
39
- context 'references_one' do
40
- let(:book) { Book.new }
41
-
42
- specify { expect { book.author_attributes = {} }.to change { book.author }.to(an_instance_of(Author)) }
43
- specify { expect { book.author_attributes = {name: 'Author'} }.to change { book.author.try(:name) }.to('Author') }
44
- specify { expect { book.author_attributes = {id: 42, name: 'Author'} }.to raise_error Granite::Form::ObjectNotFound }
45
-
46
- context ':reject_if' do
47
- context do
48
- before { Book.accepts_nested_attributes_for :author, reject_if: :all_blank }
49
- specify { expect { book.author_attributes = {name: ''} }.not_to change { book.author } }
50
- end
51
-
52
- context do
53
- before { Book.accepts_nested_attributes_for :author, reject_if: ->(attributes) { attributes['name'].blank? } }
54
- specify { expect { book.author_attributes = {name: ''} }.not_to change { book.author } }
55
- end
56
- end
57
-
58
- context 'existing' do
59
- let(:author) { Author.new(name: 'Author') }
60
- let(:book) { Book.new author: author }
61
-
62
- specify { expect { book.author_attributes = {id: 42, name: 'Author'} }.to raise_error Granite::Form::ObjectNotFound }
63
- specify { expect { book.author_attributes = {id: author.id.to_s, name: 'Author 1'} }.to change { book.author.name }.to('Author 1') }
64
- specify { expect { book.author_attributes = {name: 'Author 1'} }.to change { book.author.name }.to('Author 1') }
65
- specify { expect { book.author_attributes = {name: 'Author 1', _destroy: '1'} }.not_to change { book.author.name } }
66
- specify do
67
- expect do
68
- book.author_attributes = {name: 'Author 1', _destroy: '1'}
69
- book.save { true }
70
- end.not_to change { book.author.name }
71
- end
72
- specify { expect { book.author_attributes = {id: author.id.to_s, name: 'Author 1', _destroy: '1'} }.to change { book.author.name }.to('Author 1') }
73
- specify do
74
- expect do
75
- book.author_attributes = {id: author.id.to_s, name: 'Author 1', _destroy: '1'}
76
- book.save { true }
77
- end.to change { book.author.name }.to('Author 1')
78
- end
79
-
80
- context ':allow_destroy' do
81
- before { Book.accepts_nested_attributes_for :author, allow_destroy: true }
82
-
83
- specify { expect { book.author_attributes = {name: 'Author 1', _destroy: '1'} }.not_to change { book.author.name } }
84
- specify do
85
- expect do
86
- book.author_attributes = {name: 'Author 1', _destroy: '1'}
87
- book.save { true }
88
- end.not_to change { book.author.name }
89
- end
90
- specify { expect { book.author_attributes = {id: author.id.to_s, name: 'Author 1', _destroy: '1'} }.to change { book.author.name }.to('Author 1') }
91
- specify do
92
- expect do
93
- book.author_attributes = {id: author.id.to_s, name: 'Author 1', _destroy: '1'}
94
- book.save { true }
95
- end.to change { book.author }.to(nil)
96
- end
97
- end
98
-
99
- context ':update_only' do
100
- before { Book.accepts_nested_attributes_for :author, update_only: true }
101
-
102
- specify do
103
- expect { book.author_attributes = {id: 42, name: 'Author 1'} }
104
- .to change { book.author.name }.to('Author 1')
105
- end
106
- end
107
- end
108
- end
109
-
110
- context 'references_many' do
111
- let(:book) { Book.new }
112
- end
113
- end
114
-
115
20
  describe '#assign_attributes' do
116
21
  specify 'invent a good example'
117
22
  end