granite-form 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +26 -48
  3. data/.rubocop_todo.yml +304 -27
  4. data/CHANGELOG.md +7 -2
  5. data/granite-form.gemspec +2 -1
  6. data/lib/granite/form/active_record/associations.rb +4 -3
  7. data/lib/granite/form/config.rb +1 -1
  8. data/lib/granite/form/errors.rb +34 -32
  9. data/lib/granite/form/extensions.rb +2 -1
  10. data/lib/granite/form/model/associations/base.rb +6 -2
  11. data/lib/granite/form/model/associations/collection/embedded.rb +1 -1
  12. data/lib/granite/form/model/associations/collection/proxy.rb +3 -3
  13. data/lib/granite/form/model/associations/embeds_any.rb +1 -1
  14. data/lib/granite/form/model/associations/embeds_many.rb +15 -11
  15. data/lib/granite/form/model/associations/embeds_one.rb +9 -8
  16. data/lib/granite/form/model/associations/nested_attributes.rb +60 -32
  17. data/lib/granite/form/model/associations/persistence_adapters/active_record/referenced_proxy.rb +2 -1
  18. data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +7 -6
  19. data/lib/granite/form/model/associations/persistence_adapters/base.rb +8 -4
  20. data/lib/granite/form/model/associations/references_any.rb +1 -1
  21. data/lib/granite/form/model/associations/references_many.rb +3 -2
  22. data/lib/granite/form/model/associations/references_one.rb +1 -1
  23. data/lib/granite/form/model/associations/reflections/base.rb +3 -2
  24. data/lib/granite/form/model/associations/reflections/embeds_any.rb +4 -4
  25. data/lib/granite/form/model/associations/reflections/embeds_many.rb +4 -1
  26. data/lib/granite/form/model/associations/reflections/embeds_one.rb +4 -1
  27. data/lib/granite/form/model/associations/reflections/references_any.rb +6 -6
  28. data/lib/granite/form/model/associations/reflections/references_many.rb +1 -1
  29. data/lib/granite/form/model/associations/reflections/references_one.rb +1 -1
  30. data/lib/granite/form/model/associations/validations.rb +6 -6
  31. data/lib/granite/form/model/associations.rb +6 -4
  32. data/lib/granite/form/model/attributes/attribute.rb +1 -0
  33. data/lib/granite/form/model/attributes/base.rb +9 -7
  34. data/lib/granite/form/model/attributes/reference_one.rb +1 -1
  35. data/lib/granite/form/model/attributes/reflections/base/build_type_definition.rb +2 -1
  36. data/lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb +2 -2
  37. data/lib/granite/form/model/attributes/represents.rb +1 -1
  38. data/lib/granite/form/model/attributes.rb +21 -13
  39. data/lib/granite/form/model/conventions.rb +1 -1
  40. data/lib/granite/form/model/persistence.rb +1 -1
  41. data/lib/granite/form/model/primary.rb +1 -1
  42. data/lib/granite/form/model/representation.rb +4 -4
  43. data/lib/granite/form/model/scopes.rb +5 -5
  44. data/lib/granite/form/model/validations.rb +4 -3
  45. data/lib/granite/form/types/active_support/time_zone.rb +1 -1
  46. data/lib/granite/form/types/array.rb +1 -1
  47. data/lib/granite/form/types/big_decimal.rb +1 -1
  48. data/lib/granite/form/types/boolean.rb +1 -1
  49. data/lib/granite/form/types/date.rb +1 -1
  50. data/lib/granite/form/types/date_time.rb +1 -1
  51. data/lib/granite/form/types/dictionary.rb +1 -1
  52. data/lib/granite/form/types/float.rb +1 -1
  53. data/lib/granite/form/types/has_subtype.rb +1 -0
  54. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +2 -2
  55. data/lib/granite/form/types/integer.rb +1 -1
  56. data/lib/granite/form/types/object.rb +2 -1
  57. data/lib/granite/form/types/string.rb +1 -1
  58. data/lib/granite/form/types/time.rb +1 -1
  59. data/lib/granite/form/types/uuid.rb +1 -1
  60. data/lib/granite/form/util.rb +1 -1
  61. data/lib/granite/form/version.rb +1 -1
  62. data/spec/granite/form/active_record/associations_spec.rb +35 -13
  63. data/spec/granite/form/config_spec.rb +8 -4
  64. data/spec/granite/form/model/associations/embeds_many_spec.rb +99 -51
  65. data/spec/granite/form/model/associations/embeds_one_spec.rb +48 -25
  66. data/spec/granite/form/model/associations/persistence_adapters/active_record_spec.rb +12 -7
  67. data/spec/granite/form/model/associations/references_many_spec.rb +51 -10
  68. data/spec/granite/form/model/associations/references_one_spec.rb +17 -6
  69. data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +51 -16
  70. data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +19 -9
  71. data/spec/granite/form/model/associations/reflections/references_many_spec.rb +67 -15
  72. data/spec/granite/form/model/associations/reflections/references_one_spec.rb +34 -11
  73. data/spec/granite/form/model/associations/validations_spec.rb +16 -5
  74. data/spec/granite/form/model/associations_spec.rb +28 -9
  75. data/spec/granite/form/model/attributes/attribute_spec.rb +33 -11
  76. data/spec/granite/form/model/attributes/base_spec.rb +9 -3
  77. data/spec/granite/form/model/attributes/reflections/attribute_spec.rb +1 -0
  78. data/spec/granite/form/model/attributes/reflections/base_spec.rb +1 -0
  79. data/spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb +3 -1
  80. data/spec/granite/form/model/attributes/reflections/represents_spec.rb +2 -2
  81. data/spec/granite/form/model/attributes/represents_spec.rb +2 -2
  82. data/spec/granite/form/model/attributes_spec.rb +76 -36
  83. data/spec/granite/form/model/dirty_spec.rb +3 -0
  84. data/spec/granite/form/model/persistence_spec.rb +15 -5
  85. data/spec/granite/form/model/primary_spec.rb +17 -2
  86. data/spec/granite/form/model/representation_spec.rb +13 -3
  87. data/spec/granite/form/model/scopes_spec.rb +8 -3
  88. data/spec/granite/form/model/validations/associated_spec.rb +20 -6
  89. data/spec/granite/form/model/validations/nested_spec.rb +30 -14
  90. data/spec/granite/form/model/validations_spec.rb +1 -1
  91. data/spec/granite/form/model_spec.rb +1 -0
  92. data/spec/granite/form/types/collection_spec.rb +2 -1
  93. data/spec/granite/form/types/date_spec.rb +1 -1
  94. data/spec/granite/form/types/date_time_spec.rb +0 -2
  95. data/spec/granite/form/types/dictionary_spec.rb +1 -0
  96. data/spec/granite/form/types/has_subtype_spec.rb +6 -1
  97. data/spec/granite/form/types/hash_with_action_controller_parameters_spec.rb +1 -1
  98. data/spec/granite/form/types/object_spec.rb +2 -0
  99. data/spec/granite/form/types/time_spec.rb +0 -2
  100. data/spec/granite/form/util_spec.rb +6 -3
  101. data/spec/support/active_record.rb +13 -0
  102. data/spec/support/shared/nested_attribute_examples.rb +110 -54
  103. metadata +23 -9
@@ -4,7 +4,8 @@ describe Granite::Form::Config do
4
4
  subject { Granite::Form::Config.send :new }
5
5
 
6
6
  describe '#include_root_in_json' do
7
- its(:include_root_in_json) { should == false }
7
+ its(:include_root_in_json) { is_expected.to eq false }
8
+
8
9
  specify do
9
10
  expect { subject.include_root_in_json = true }
10
11
  .to change { subject.include_root_in_json }.from(false).to(true)
@@ -12,7 +13,8 @@ describe Granite::Form::Config do
12
13
  end
13
14
 
14
15
  describe '#i18n_scope' do
15
- its(:i18n_scope) { should == :granite }
16
+ its(:i18n_scope) { is_expected.to eq :granite }
17
+
16
18
  specify do
17
19
  expect { subject.i18n_scope = :data_model }
18
20
  .to change { subject.i18n_scope }.from(:granite).to(:data_model)
@@ -20,11 +22,12 @@ describe Granite::Form::Config do
20
22
  end
21
23
 
22
24
  describe '#logger' do
23
- its(:logger) { should be_a Logger }
25
+ its(:logger) { is_expected.to be_a Logger }
24
26
  end
25
27
 
26
28
  describe '#primary_attribute' do
27
- its(:primary_attribute) { should == :id }
29
+ its(:primary_attribute) { is_expected.to eq :id }
30
+
28
31
  specify do
29
32
  expect { subject.primary_attribute = :identified }
30
33
  .to change { subject.primary_attribute }.from(:id).to(:identified)
@@ -42,6 +45,7 @@ describe Granite::Form::Config do
42
45
  end
43
46
  }.from(nil).to(an_instance_of(Proc))
44
47
  end
48
+
45
49
  specify { expect { subject.normalizer(:wrong) }.to raise_error Granite::Form::NormalizerMissing }
46
50
  end
47
51
 
@@ -25,19 +25,20 @@ describe Granite::Form::Model::Associations::EmbedsMany do
25
25
  let(:user) { User.new(name: 'User') }
26
26
  let(:association) { user.association(:projects) }
27
27
 
28
- let(:existing_user) { User.instantiate name: 'Rick', projects: [{title: 'Genesis'}] }
28
+ let(:existing_user) { User.instantiate name: 'Rick', projects: [{ title: 'Genesis' }] }
29
29
  let(:existing_association) { existing_user.association(:projects) }
30
30
 
31
31
  context 'callbacks' do
32
32
  before do
33
33
  User.class_eval do
34
34
  embeds_many :projects,
35
- before_add: ->(object) { callbacks.push([:before_add, object]) },
36
- after_add: ->(object) { callbacks.push([:after_add, object]) }
35
+ before_add: ->(object) { callbacks.push([:before_add, object]) },
36
+ after_add: ->(object) { callbacks.push([:after_add, object]) }
37
37
 
38
38
  collection :callbacks, Array
39
39
  end
40
40
  end
41
+
41
42
  let(:project1) { Project.new(title: 'Project1') }
42
43
  let(:project2) { Project.new(title: 'Project2') }
43
44
 
@@ -54,18 +55,18 @@ describe Granite::Form::Model::Associations::EmbedsMany do
54
55
  end
55
56
  .to change { user.callbacks }
56
57
  .to([
57
- [:before_add, project1], [:after_add, project1],
58
- [:before_add, project2], [:after_add, project2]
59
- ])
58
+ [:before_add, project1], [:after_add, project1],
59
+ [:before_add, project2], [:after_add, project2]
60
+ ])
60
61
  end
61
62
 
62
63
  specify do
63
64
  expect { association.concat(project1, project2) }
64
65
  .to change { user.callbacks }
65
66
  .to([
66
- [:before_add, project1], [:after_add, project1],
67
- [:before_add, project2], [:after_add, project2]
68
- ])
67
+ [:before_add, project1], [:after_add, project1],
68
+ [:before_add, project2], [:after_add, project2]
69
+ ])
69
70
  end
70
71
 
71
72
  specify do
@@ -75,18 +76,18 @@ describe Granite::Form::Model::Associations::EmbedsMany do
75
76
  end
76
77
  .to change { user.callbacks }
77
78
  .to([
78
- [:before_add, project1], [:after_add, project1],
79
- [:before_add, project2], [:after_add, project2]
80
- ])
79
+ [:before_add, project1], [:after_add, project1],
80
+ [:before_add, project2], [:after_add, project2]
81
+ ])
81
82
  end
82
83
 
83
84
  specify do
84
85
  expect { association.writer([project2, project1]) }
85
86
  .to change { user.callbacks }
86
87
  .to([
87
- [:before_add, project2], [:after_add, project2],
88
- [:before_add, project1], [:after_add, project1]
89
- ])
88
+ [:before_add, project2], [:after_add, project2],
89
+ [:before_add, project1], [:after_add, project1]
90
+ ])
90
91
  end
91
92
 
92
93
  specify do
@@ -97,18 +98,18 @@ describe Granite::Form::Model::Associations::EmbedsMany do
97
98
  end
98
99
  .to change { user.callbacks }
99
100
  .to([
100
- [:before_add, project1], [:after_add, project1],
101
- [:before_add, project2], [:after_add, project2]
102
- ])
101
+ [:before_add, project1], [:after_add, project1],
102
+ [:before_add, project2], [:after_add, project2]
103
+ ])
103
104
  end
104
105
 
105
106
  context 'default' do
106
107
  before do
107
108
  User.class_eval do
108
109
  embeds_many :projects,
109
- before_add: ->(owner, object) { owner.callbacks.push([:before_add, object]) },
110
- after_add: ->(owner, object) { owner.callbacks.push([:after_add, object]) },
111
- default: -> { {title: 'Project1'} }
110
+ before_add: ->(owner, object) { owner.callbacks.push([:before_add, object]) },
111
+ after_add: ->(owner, object) { owner.callbacks.push([:after_add, object]) },
112
+ default: -> { { title: 'Project1' } }
112
113
 
113
114
  collection :callbacks, Array
114
115
  end
@@ -118,9 +119,9 @@ describe Granite::Form::Model::Associations::EmbedsMany do
118
119
  expect { association.concat(project2) }
119
120
  .to change { user.callbacks }
120
121
  .to([
121
- [:before_add, project2], [:after_add, project2],
122
- [:before_add, project1], [:after_add, project1]
123
- ])
122
+ [:before_add, project2], [:after_add, project2],
123
+ [:before_add, project1], [:after_add, project1]
124
+ ])
124
125
  end
125
126
  end
126
127
  end
@@ -134,14 +135,17 @@ describe Granite::Form::Model::Associations::EmbedsMany do
134
135
  let(:project) { Project.new(title: 'Project') }
135
136
 
136
137
  specify { expect(association.build.embedder).to eq(user) }
138
+
137
139
  specify do
138
140
  expect { association.writer([project]) }
139
141
  .to change { project.embedder }.from(nil).to(user)
140
142
  end
143
+
141
144
  specify do
142
145
  expect { association.concat(project) }
143
146
  .to change { project.embedder }.from(nil).to(user)
144
147
  end
148
+
145
149
  specify do
146
150
  expect { association.target = [project] }
147
151
  .to change { project.embedder }.from(nil).to(user)
@@ -150,7 +154,7 @@ describe Granite::Form::Model::Associations::EmbedsMany do
150
154
  context 'default' do
151
155
  before do
152
156
  User.class_eval do
153
- embeds_many :projects, default: -> { {title: 'Project1'} }
157
+ embeds_many :projects, default: -> { { title: 'Project1' } }
154
158
  end
155
159
  end
156
160
 
@@ -184,22 +188,24 @@ describe Granite::Form::Model::Associations::EmbedsMany do
184
188
 
185
189
  specify do
186
190
  expect { association.build(title: 'Swordfish') }
187
- .not_to change { user.read_attribute(:projects) }
191
+ .not_to(change { user.read_attribute(:projects) })
188
192
  end
193
+
189
194
  specify do
190
195
  expect { association.build(title: 'Swordfish') }
191
196
  .to change { association.reader.map(&:attributes) }
192
- .from([]).to([{'title' => 'Swordfish'}])
197
+ .from([]).to([{ 'title' => 'Swordfish' }])
193
198
  end
194
199
 
195
200
  specify do
196
201
  expect { existing_association.build(title: 'Swordfish') }
197
- .not_to change { existing_user.read_attribute(:projects) }
202
+ .not_to(change { existing_user.read_attribute(:projects) })
198
203
  end
204
+
199
205
  specify do
200
206
  expect { existing_association.build(title: 'Swordfish') }
201
207
  .to change { existing_association.reader.map(&:attributes) }
202
- .from([{'title' => 'Genesis'}]).to([{'title' => 'Genesis'}, {'title' => 'Swordfish'}])
208
+ .from([{ 'title' => 'Genesis' }]).to([{ 'title' => 'Genesis' }, { 'title' => 'Swordfish' }])
203
209
  end
204
210
  end
205
211
 
@@ -210,27 +216,41 @@ describe Granite::Form::Model::Associations::EmbedsMany do
210
216
  end
211
217
 
212
218
  describe '#default' do
213
- before { User.embeds_many :projects, default: -> { {title: 'Default'} } }
214
219
  before do
220
+ User.embeds_many :projects, default: -> { { title: 'Default' } }
215
221
  Project.class_eval do
216
222
  include Granite::Form::Model::Primary
217
223
  primary :title
218
224
  end
219
225
  end
226
+
220
227
  let(:new_project) { Project.new.tap { |p| p.title = 'Project' } }
221
228
  let(:existing_user) { User.instantiate name: 'Rick' }
222
229
 
223
230
  specify { expect(association.target.map(&:title)).to eq(['Default']) }
224
231
  specify { expect(association.target.map(&:new_record?)).to eq([true]) }
225
- specify { expect { association.replace([new_project]) }.to change { association.target.map(&:title) }.to eq(['Project']) }
232
+
233
+ specify do
234
+ expect { association.replace([new_project]) }
235
+ .to change { association.target.map(&:title) }
236
+ .to eq(['Project'])
237
+ end
238
+
226
239
  specify { expect { association.replace([]) }.to change { association.target }.to([]) }
227
240
 
228
241
  specify { expect(existing_association.target).to eq([]) }
229
- specify { expect { existing_association.replace([new_project]) }.to change { existing_association.target.map(&:title) }.to(['Project']) }
230
- specify { expect { existing_association.replace([]) }.not_to change { existing_association.target } }
242
+
243
+ specify do
244
+ expect { existing_association.replace([new_project]) }
245
+ .to change { existing_association.target.map(&:title) }
246
+ .to(['Project'])
247
+ end
248
+
249
+ specify { expect { existing_association.replace([]) }.not_to(change { existing_association.target }) }
231
250
 
232
251
  context do
233
- before { Project.send(:include, Granite::Form::Model::Dirty) }
252
+ before { Project.include Granite::Form::Model::Dirty }
253
+
234
254
  specify { expect(association.target.any?(&:changed?)).to eq(false) }
235
255
  end
236
256
  end
@@ -250,18 +270,20 @@ describe Granite::Form::Model::Associations::EmbedsMany do
250
270
 
251
271
  context do
252
272
  before { association.build(title: 'Swordfish') }
273
+
253
274
  specify do
254
275
  expect { association.reload }
255
- .to change { association.reader.map(&:attributes) }.from([{'title' => 'Swordfish'}]).to([])
276
+ .to change { association.reader.map(&:attributes) }.from([{ 'title' => 'Swordfish' }]).to([])
256
277
  end
257
278
  end
258
279
 
259
280
  context do
260
281
  before { existing_association.build(title: 'Swordfish') }
282
+
261
283
  specify do
262
284
  expect { existing_association.reload }
263
285
  .to change { existing_association.reader.map(&:attributes) }
264
- .from([{'title' => 'Genesis'}, {'title' => 'Swordfish'}]).to([{'title' => 'Genesis'}])
286
+ .from([{ 'title' => 'Genesis' }, { 'title' => 'Swordfish' }]).to([{ 'title' => 'Genesis' }])
265
287
  end
266
288
  end
267
289
  end
@@ -270,7 +292,7 @@ describe Granite::Form::Model::Associations::EmbedsMany do
270
292
  let!(:project) { association.build(title: 'Genesis') }
271
293
 
272
294
  specify do
273
- expect { association.sync }.to change { user.read_attribute(:projects) }.from(nil).to([{'title' => 'Genesis'}])
295
+ expect { association.sync }.to change { user.read_attribute(:projects) }.from(nil).to([{ 'title' => 'Genesis' }])
274
296
  end
275
297
 
276
298
  context 'when embedding is nested' do
@@ -288,19 +310,20 @@ describe Granite::Form::Model::Associations::EmbedsMany do
288
310
 
289
311
  specify do
290
312
  expect { association.sync }.to change { user.read_attribute(:projects) }
291
- .from(nil).to([{'title' => 'Genesis', 'deadline' => {'enabled' => true}}])
313
+ .from(nil).to([{ 'title' => 'Genesis', 'deadline' => { 'enabled' => true } }])
292
314
  end
293
315
  end
294
316
  end
295
317
 
296
318
  describe '#clear' do
297
319
  specify { expect(association.clear).to eq(true) }
298
- specify { expect { association.clear }.not_to change { association.reader } }
320
+ specify { expect { association.clear }.not_to(change { association.reader }) }
299
321
 
300
322
  specify { expect(existing_association.clear).to eq(true) }
323
+
301
324
  specify do
302
325
  expect { existing_association.clear }
303
- .to change { existing_association.reader.map(&:attributes) }.from([{'title' => 'Genesis'}]).to([])
326
+ .to change { existing_association.reader.map(&:attributes) }.from([{ 'title' => 'Genesis' }]).to([])
304
327
  end
305
328
  end
306
329
 
@@ -312,6 +335,7 @@ describe Granite::Form::Model::Associations::EmbedsMany do
312
335
 
313
336
  context do
314
337
  before { association.build }
338
+
315
339
  specify { expect(association.reader.last).to be_a Project }
316
340
  specify { expect(association.reader.last).not_to be_persisted }
317
341
  specify { expect(association.reader.size).to eq(1) }
@@ -320,6 +344,7 @@ describe Granite::Form::Model::Associations::EmbedsMany do
320
344
 
321
345
  context do
322
346
  before { existing_association.build(title: 'Swordfish') }
347
+
323
348
  specify { expect(existing_association.reader.size).to eq(2) }
324
349
  specify { expect(existing_association.reader.last.title).to eq('Swordfish') }
325
350
  specify { expect(existing_association.reader(true).size).to eq(1) }
@@ -342,37 +367,45 @@ describe Granite::Form::Model::Associations::EmbedsMany do
342
367
  specify { expect(association.writer([])).to eq([]) }
343
368
 
344
369
  specify { expect(association.writer([new_project1])).to eq([new_project1]) }
370
+
345
371
  specify do
346
372
  expect { association.writer([new_project1]) }
347
- .to change { association.reader.map(&:attributes) }.from([]).to([{'title' => 'Project 1'}])
373
+ .to change { association.reader.map(&:attributes) }.from([]).to([{ 'title' => 'Project 1' }])
348
374
  end
349
375
 
350
376
  specify do
351
377
  expect { existing_association.writer([new_project1, Dummy.new, new_project2]) }
352
378
  .to raise_error Granite::Form::AssociationTypeMismatch
353
379
  end
380
+
354
381
  specify do
355
- expect { muffle(Granite::Form::AssociationTypeMismatch) { existing_association.writer([new_project1, Dummy.new, new_project2]) } }
356
- .not_to change { existing_association.reader }
382
+ expect do
383
+ muffle(Granite::Form::AssociationTypeMismatch) do
384
+ existing_association.writer([new_project1, Dummy.new, new_project2])
385
+ end
386
+ end.not_to(change { existing_association.reader })
357
387
  end
358
388
 
359
389
  specify { expect { existing_association.writer(nil) }.to raise_error NoMethodError }
390
+
360
391
  specify do
361
392
  expect { muffle(NoMethodError) { existing_association.writer(nil) } }
362
- .not_to change { existing_association.reader }
393
+ .not_to(change { existing_association.reader })
363
394
  end
364
395
 
365
396
  specify { expect(existing_association.writer([])).to eq([]) }
397
+
366
398
  specify do
367
399
  expect { existing_association.writer([]) }
368
400
  .to change { existing_association.reader }.to([])
369
401
  end
370
402
 
371
403
  specify { expect(existing_association.writer([new_project1, new_project2])).to eq([new_project1, new_project2]) }
404
+
372
405
  specify do
373
406
  expect { existing_association.writer([new_project1, new_project2]) }
374
407
  .to change { existing_association.reader.map(&:attributes) }
375
- .from([{'title' => 'Genesis'}]).to([{'title' => 'Project 1'}, {'title' => 'Project 2'}])
408
+ .from([{ 'title' => 'Genesis' }]).to([{ 'title' => 'Project 1' }, { 'title' => 'Project 2' }])
376
409
  end
377
410
  end
378
411
 
@@ -392,39 +425,54 @@ describe Granite::Form::Model::Associations::EmbedsMany do
392
425
  specify { expect(existing_association.concat).to eq(existing_user.projects) }
393
426
 
394
427
  specify { expect(association.concat(new_project1)).to eq([new_project1]) }
428
+
395
429
  specify do
396
430
  expect { association.concat(new_project1) }
397
- .to change { association.reader.map(&:attributes) }.from([]).to([{'title' => 'Project 1'}])
431
+ .to change { association.reader.map(&:attributes) }.from([]).to([{ 'title' => 'Project 1' }])
398
432
  end
433
+
399
434
  specify do
400
435
  expect { association.concat(new_project1) }
401
- .not_to change { user.read_attribute(:projects) }
436
+ .not_to(change { user.read_attribute(:projects) })
402
437
  end
403
438
 
404
439
  specify do
405
440
  expect { existing_association.concat(new_project1, invalid_project) }
406
441
  .to change { existing_association.reader.map(&:attributes) }
407
- .from([{'title' => 'Genesis'}]).to([{'title' => 'Genesis'}, {'title' => 'Project 1'}, {'title' => nil}])
442
+ .from([{ 'title' => 'Genesis' }])
443
+ .to([
444
+ { 'title' => 'Genesis' },
445
+ { 'title' => 'Project 1' },
446
+ { 'title' => nil }
447
+ ])
408
448
  end
409
449
 
410
450
  specify do
411
451
  expect { existing_association.concat(new_project1, Dummy.new, new_project2) }
412
452
  .to raise_error Granite::Form::AssociationTypeMismatch
413
453
  end
454
+
414
455
  specify do
415
- expect { muffle(Granite::Form::AssociationTypeMismatch) { existing_association.concat(new_project1, Dummy.new, new_project2) } }
456
+ expect do
457
+ muffle(Granite::Form::AssociationTypeMismatch) do
458
+ existing_association.concat(new_project1, Dummy.new, new_project2)
459
+ end
460
+ end
416
461
  .to change { existing_association.reader.map(&:attributes) }
417
- .from([{'title' => 'Genesis'}]).to([{'title' => 'Genesis'}, {'title' => 'Project 1'}])
462
+ .from([{ 'title' => 'Genesis' }]).to([{ 'title' => 'Genesis' }, { 'title' => 'Project 1' }])
418
463
  end
419
464
 
420
465
  specify do
421
466
  expect(existing_association.concat(new_project1, new_project2))
422
467
  .to eq([existing_user.projects.first, new_project1, new_project2])
423
468
  end
469
+
424
470
  specify do
425
471
  expect { existing_association.concat([new_project1, new_project2]) }
426
472
  .to change { existing_association.reader.map(&:attributes) }
427
- .from([{'title' => 'Genesis'}]).to([{'title' => 'Genesis'}, {'title' => 'Project 1'}, {'title' => 'Project 2'}])
473
+ .from([{ 'title' => 'Genesis' }]).to([{ 'title' => 'Genesis' },
474
+ { 'title' => 'Project 1' },
475
+ { 'title' => 'Project 2' }])
428
476
  end
429
477
  end
430
478
  end
@@ -22,7 +22,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
22
22
  let(:book) { Book.new(title: 'Book') }
23
23
  let(:association) { book.association(:author) }
24
24
 
25
- let(:existing_book) { Book.instantiate title: 'My Life', author: {'name' => 'Johny'} }
25
+ let(:existing_book) { Book.instantiate title: 'My Life', author: { 'name' => 'Johny' } }
26
26
  let(:existing_association) { existing_book.association(:author) }
27
27
 
28
28
  context 'callbacks' do
@@ -41,6 +41,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
41
41
  collection :callbacks, Array
42
42
  end
43
43
  end
44
+
44
45
  let(:author1) { Author.new(name: 'Author1') }
45
46
  let(:author2) { Author.new(name: 'Author2') }
46
47
 
@@ -57,9 +58,9 @@ describe Granite::Form::Model::Associations::EmbedsOne do
57
58
  end
58
59
  .to change { book.callbacks }
59
60
  .to([
60
- [:before_add, author1], [:after_add, author1],
61
- [:before_add, author2], [:after_add, author2]
62
- ])
61
+ [:before_add, author1], [:after_add, author1],
62
+ [:before_add, author2], [:after_add, author2]
63
+ ])
63
64
  end
64
65
 
65
66
  specify do
@@ -76,18 +77,18 @@ describe Granite::Form::Model::Associations::EmbedsOne do
76
77
  end
77
78
  .to change { book.callbacks }
78
79
  .to([
79
- [:before_add, author1], [:after_add, author1],
80
- [:before_add, author1], [:after_add, author1]
81
- ])
80
+ [:before_add, author1], [:after_add, author1],
81
+ [:before_add, author1], [:after_add, author1]
82
+ ])
82
83
  end
83
84
 
84
85
  context 'default' do
85
86
  before do
86
87
  Book.class_eval do
87
88
  embeds_one :author,
88
- before_add: ->(object) { callbacks.push([:before_add, object]) },
89
- after_add: ->(object) { callbacks.push([:after_add, object]) },
90
- default: -> { {name: 'Author1'} }
89
+ before_add: ->(object) { callbacks.push([:before_add, object]) },
90
+ after_add: ->(object) { callbacks.push([:after_add, object]) },
91
+ default: -> { { name: 'Author1' } }
91
92
 
92
93
  collection :callbacks, Array
93
94
  end
@@ -97,9 +98,9 @@ describe Granite::Form::Model::Associations::EmbedsOne do
97
98
  expect { association.writer(author2) }
98
99
  .to change { book.callbacks }
99
100
  .to([
100
- [:before_add, author1], [:after_add, author1],
101
- [:before_add, author2], [:after_add, author2]
102
- ])
101
+ [:before_add, author1], [:after_add, author1],
102
+ [:before_add, author2], [:after_add, author2]
103
+ ])
103
104
  end
104
105
  end
105
106
  end
@@ -113,10 +114,12 @@ describe Granite::Form::Model::Associations::EmbedsOne do
113
114
  let(:author) { Author.new(name: 'Author') }
114
115
 
115
116
  specify { expect(association.build.embedder).to eq(book) }
117
+
116
118
  specify do
117
119
  expect { association.writer(author) }
118
120
  .to change { author.embedder }.from(nil).to(book)
119
121
  end
122
+
120
123
  specify do
121
124
  expect { association.target = author }
122
125
  .to change { author.embedder }.from(nil).to(book)
@@ -125,7 +128,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
125
128
  context 'default' do
126
129
  before do
127
130
  Book.class_eval do
128
- embeds_one :author, default: -> { {name: 'Author1'} }
131
+ embeds_one :author, default: -> { { name: 'Author1' } }
129
132
  end
130
133
  end
131
134
 
@@ -159,12 +162,12 @@ describe Granite::Form::Model::Associations::EmbedsOne do
159
162
 
160
163
  specify do
161
164
  expect { association.build(name: 'Fred') }
162
- .not_to change { book.read_attribute(:author) }
165
+ .not_to(change { book.read_attribute(:author) })
163
166
  end
164
167
 
165
168
  specify do
166
169
  expect { existing_association.build(name: 'Fred') }
167
- .not_to change { existing_book.read_attribute(:author) }
170
+ .not_to(change { existing_book.read_attribute(:author) })
168
171
  end
169
172
  end
170
173
 
@@ -175,13 +178,14 @@ describe Granite::Form::Model::Associations::EmbedsOne do
175
178
  end
176
179
 
177
180
  describe '#default' do
178
- before { Book.embeds_one :author, default: -> { {name: 'Default'} } }
179
181
  before do
182
+ Book.embeds_one :author, default: -> { { name: 'Default' } }
180
183
  Author.class_eval do
181
184
  include Granite::Form::Model::Primary
182
185
  primary :name
183
186
  end
184
187
  end
188
+
185
189
  let(:new_author) { Author.new.tap { |a| a.name = 'Morty' } }
186
190
  let(:existing_book) { Book.instantiate title: 'My Life' }
187
191
 
@@ -191,11 +195,18 @@ describe Granite::Form::Model::Associations::EmbedsOne do
191
195
  specify { expect { association.replace(nil) }.to change { association.target }.to be_nil }
192
196
 
193
197
  specify { expect(existing_association.target).to be_nil }
194
- specify { expect { existing_association.replace(new_author) }.to change { existing_association.target }.to(an_instance_of(Author)) }
195
- specify { expect { existing_association.replace(nil) }.not_to change { existing_association.target } }
198
+
199
+ specify do
200
+ expect { existing_association.replace(new_author) }
201
+ .to change { existing_association.target }
202
+ .to(an_instance_of(Author))
203
+ end
204
+
205
+ specify { expect { existing_association.replace(nil) }.not_to(change { existing_association.target }) }
196
206
 
197
207
  context do
198
- before { Author.send(:include, Granite::Form::Model::Dirty) }
208
+ before { Author.include Granite::Form::Model::Dirty }
209
+
199
210
  specify { expect(association.target).not_to be_changed }
200
211
  end
201
212
  end
@@ -220,6 +231,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
220
231
 
221
232
  context do
222
233
  before { association.build(name: 'Fred') }
234
+
223
235
  specify do
224
236
  expect { association.reload }
225
237
  .to change { association.reader.try(:attributes) }.from('name' => 'Fred').to(nil)
@@ -228,6 +240,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
228
240
 
229
241
  context do
230
242
  before { existing_association.build(name: 'Fred') }
243
+
231
244
  specify do
232
245
  expect { existing_association.reload }
233
246
  .to change { existing_association.reader.try(:attributes) }
@@ -256,16 +269,17 @@ describe Granite::Form::Model::Associations::EmbedsOne do
256
269
 
257
270
  specify do
258
271
  expect { association.sync }.to change { book.read_attribute(:author) }
259
- .from(nil).to('name' => 'Fred', 'reviews' => [{'rating' => 7}])
272
+ .from(nil).to('name' => 'Fred', 'reviews' => [{ 'rating' => 7 }])
260
273
  end
261
274
  end
262
275
  end
263
276
 
264
277
  describe '#clear' do
265
278
  specify { expect(association.clear).to eq(true) }
266
- specify { expect { association.clear }.not_to change { association.reader } }
279
+ specify { expect { association.clear }.not_to(change { association.reader }) }
267
280
 
268
281
  specify { expect(existing_association.clear).to eq(true) }
282
+
269
283
  specify do
270
284
  expect { existing_association.clear }
271
285
  .to change { existing_association.reader.try(:attributes) }.from('name' => 'Johny').to(nil)
@@ -280,6 +294,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
280
294
 
281
295
  context do
282
296
  before { association.build }
297
+
283
298
  specify { expect(association.reader).to be_a Author }
284
299
  specify { expect(association.reader).not_to be_persisted }
285
300
  specify { expect(association.reader(true)).to be_nil }
@@ -287,6 +302,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
287
302
 
288
303
  context do
289
304
  before { existing_association.build(name: 'Fred') }
305
+
290
306
  specify { expect(existing_association.reader.name).to eq('Fred') }
291
307
  specify { expect(existing_association.reader(true).name).to eq('Johny') }
292
308
  end
@@ -305,8 +321,9 @@ describe Granite::Form::Model::Associations::EmbedsOne do
305
321
 
306
322
  specify do
307
323
  expect { association.writer(nil) }
308
- .not_to change { book.read_attribute(:author) }
324
+ .not_to(change { book.read_attribute(:author) })
309
325
  end
326
+
310
327
  specify do
311
328
  expect { association.writer(new_author) }
312
329
  .to change { association.reader.try(:attributes) }.from(nil).to('name' => 'Morty')
@@ -321,6 +338,7 @@ describe Granite::Form::Model::Associations::EmbedsOne do
321
338
 
322
339
  specify { expect(association.writer(nil)).to be_nil }
323
340
  specify { expect(association.writer(new_author)).to eq(new_author) }
341
+
324
342
  specify do
325
343
  expect { association.writer(new_author) }
326
344
  .to change { association.reader.try(:attributes) }.from(nil).to('name' => 'Morty')
@@ -332,12 +350,17 @@ describe Granite::Form::Model::Associations::EmbedsOne do
332
350
  end
333
351
 
334
352
  specify do
335
- expect { muffle(Granite::Form::AssociationTypeMismatch) { existing_association.writer(stub_model(:dummy).new) } }
336
- .not_to change { existing_association.reader }
353
+ expect do
354
+ muffle(Granite::Form::AssociationTypeMismatch) do
355
+ existing_association.writer(stub_model(:dummy).new)
356
+ end
357
+ end
358
+ .not_to(change { existing_association.reader })
337
359
  end
338
360
 
339
361
  specify { expect(existing_association.writer(nil)).to be_nil }
340
362
  specify { expect(existing_association.writer(new_author)).to eq(new_author) }
363
+
341
364
  specify do
342
365
  expect { existing_association.writer(new_author) }
343
366
  .to change { existing_association.reader.try(:attributes) }