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.
- checksums.yaml +4 -4
- data/.rubocop.yml +26 -48
- data/.rubocop_todo.yml +304 -27
- data/CHANGELOG.md +7 -2
- data/granite-form.gemspec +2 -1
- data/lib/granite/form/active_record/associations.rb +4 -3
- data/lib/granite/form/config.rb +1 -1
- data/lib/granite/form/errors.rb +34 -32
- data/lib/granite/form/extensions.rb +2 -1
- data/lib/granite/form/model/associations/base.rb +6 -2
- data/lib/granite/form/model/associations/collection/embedded.rb +1 -1
- data/lib/granite/form/model/associations/collection/proxy.rb +3 -3
- data/lib/granite/form/model/associations/embeds_any.rb +1 -1
- data/lib/granite/form/model/associations/embeds_many.rb +15 -11
- data/lib/granite/form/model/associations/embeds_one.rb +9 -8
- data/lib/granite/form/model/associations/nested_attributes.rb +60 -32
- data/lib/granite/form/model/associations/persistence_adapters/active_record/referenced_proxy.rb +2 -1
- data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +7 -6
- data/lib/granite/form/model/associations/persistence_adapters/base.rb +8 -4
- data/lib/granite/form/model/associations/references_any.rb +1 -1
- data/lib/granite/form/model/associations/references_many.rb +3 -2
- data/lib/granite/form/model/associations/references_one.rb +1 -1
- data/lib/granite/form/model/associations/reflections/base.rb +3 -2
- data/lib/granite/form/model/associations/reflections/embeds_any.rb +4 -4
- data/lib/granite/form/model/associations/reflections/embeds_many.rb +4 -1
- data/lib/granite/form/model/associations/reflections/embeds_one.rb +4 -1
- data/lib/granite/form/model/associations/reflections/references_any.rb +6 -6
- data/lib/granite/form/model/associations/reflections/references_many.rb +1 -1
- data/lib/granite/form/model/associations/reflections/references_one.rb +1 -1
- data/lib/granite/form/model/associations/validations.rb +6 -6
- data/lib/granite/form/model/associations.rb +6 -4
- data/lib/granite/form/model/attributes/attribute.rb +1 -0
- data/lib/granite/form/model/attributes/base.rb +9 -7
- data/lib/granite/form/model/attributes/reference_one.rb +1 -1
- data/lib/granite/form/model/attributes/reflections/base/build_type_definition.rb +2 -1
- data/lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb +2 -2
- data/lib/granite/form/model/attributes/represents.rb +1 -1
- data/lib/granite/form/model/attributes.rb +21 -13
- data/lib/granite/form/model/conventions.rb +1 -1
- data/lib/granite/form/model/persistence.rb +1 -1
- data/lib/granite/form/model/primary.rb +1 -1
- data/lib/granite/form/model/representation.rb +4 -4
- data/lib/granite/form/model/scopes.rb +5 -5
- data/lib/granite/form/model/validations.rb +4 -3
- data/lib/granite/form/types/active_support/time_zone.rb +1 -1
- data/lib/granite/form/types/array.rb +1 -1
- data/lib/granite/form/types/big_decimal.rb +1 -1
- data/lib/granite/form/types/boolean.rb +1 -1
- data/lib/granite/form/types/date.rb +1 -1
- data/lib/granite/form/types/date_time.rb +1 -1
- data/lib/granite/form/types/dictionary.rb +1 -1
- data/lib/granite/form/types/float.rb +1 -1
- data/lib/granite/form/types/has_subtype.rb +1 -0
- data/lib/granite/form/types/hash_with_action_controller_parameters.rb +2 -2
- data/lib/granite/form/types/integer.rb +1 -1
- data/lib/granite/form/types/object.rb +2 -1
- data/lib/granite/form/types/string.rb +1 -1
- data/lib/granite/form/types/time.rb +1 -1
- data/lib/granite/form/types/uuid.rb +1 -1
- data/lib/granite/form/util.rb +1 -1
- data/lib/granite/form/version.rb +1 -1
- data/spec/granite/form/active_record/associations_spec.rb +35 -13
- data/spec/granite/form/config_spec.rb +8 -4
- data/spec/granite/form/model/associations/embeds_many_spec.rb +99 -51
- data/spec/granite/form/model/associations/embeds_one_spec.rb +48 -25
- data/spec/granite/form/model/associations/persistence_adapters/active_record_spec.rb +12 -7
- data/spec/granite/form/model/associations/references_many_spec.rb +51 -10
- data/spec/granite/form/model/associations/references_one_spec.rb +17 -6
- data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +51 -16
- data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +19 -9
- data/spec/granite/form/model/associations/reflections/references_many_spec.rb +67 -15
- data/spec/granite/form/model/associations/reflections/references_one_spec.rb +34 -11
- data/spec/granite/form/model/associations/validations_spec.rb +16 -5
- data/spec/granite/form/model/associations_spec.rb +28 -9
- data/spec/granite/form/model/attributes/attribute_spec.rb +33 -11
- data/spec/granite/form/model/attributes/base_spec.rb +9 -3
- data/spec/granite/form/model/attributes/reflections/attribute_spec.rb +1 -0
- data/spec/granite/form/model/attributes/reflections/base_spec.rb +1 -0
- data/spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb +3 -1
- data/spec/granite/form/model/attributes/reflections/represents_spec.rb +2 -2
- data/spec/granite/form/model/attributes/represents_spec.rb +2 -2
- data/spec/granite/form/model/attributes_spec.rb +76 -36
- data/spec/granite/form/model/dirty_spec.rb +3 -0
- data/spec/granite/form/model/persistence_spec.rb +15 -5
- data/spec/granite/form/model/primary_spec.rb +17 -2
- data/spec/granite/form/model/representation_spec.rb +13 -3
- data/spec/granite/form/model/scopes_spec.rb +8 -3
- data/spec/granite/form/model/validations/associated_spec.rb +20 -6
- data/spec/granite/form/model/validations/nested_spec.rb +30 -14
- data/spec/granite/form/model/validations_spec.rb +1 -1
- data/spec/granite/form/model_spec.rb +1 -0
- data/spec/granite/form/types/collection_spec.rb +2 -1
- data/spec/granite/form/types/date_spec.rb +1 -1
- data/spec/granite/form/types/date_time_spec.rb +0 -2
- data/spec/granite/form/types/dictionary_spec.rb +1 -0
- data/spec/granite/form/types/has_subtype_spec.rb +6 -1
- data/spec/granite/form/types/hash_with_action_controller_parameters_spec.rb +1 -1
- data/spec/granite/form/types/object_spec.rb +2 -0
- data/spec/granite/form/types/time_spec.rb +0 -2
- data/spec/granite/form/util_spec.rb +6 -3
- data/spec/support/active_record.rb +13 -0
- data/spec/support/shared/nested_attribute_examples.rb +110 -54
- 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) {
|
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) {
|
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) {
|
25
|
+
its(:logger) { is_expected.to be_a Logger }
|
24
26
|
end
|
25
27
|
|
26
28
|
describe '#primary_attribute' do
|
27
|
-
its(:primary_attribute) {
|
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
|
-
|
36
|
-
|
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
|
-
|
58
|
-
|
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
|
-
|
67
|
-
|
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
|
-
|
79
|
-
|
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
|
-
|
88
|
-
|
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
|
-
|
101
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
122
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
230
|
-
specify
|
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.
|
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
|
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
|
356
|
-
|
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
|
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
|
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([{
|
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
|
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'
|
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
|
-
|
61
|
-
|
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
|
-
|
80
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
101
|
-
|
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
|
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
|
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
|
-
|
195
|
-
specify
|
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.
|
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
|
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
|
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
|
336
|
-
|
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) }
|