copyable 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +264 -0
- data/Rakefile +7 -0
- data/copyable.gemspec +28 -0
- data/lib/copyable.rb +32 -0
- data/lib/copyable/config.rb +19 -0
- data/lib/copyable/copy_registry.rb +50 -0
- data/lib/copyable/copyable_extension.rb +118 -0
- data/lib/copyable/declarations/after_copy.rb +15 -0
- data/lib/copyable/declarations/associations.rb +116 -0
- data/lib/copyable/declarations/columns.rb +34 -0
- data/lib/copyable/declarations/declaration.rb +15 -0
- data/lib/copyable/declarations/declarations.rb +14 -0
- data/lib/copyable/declarations/disable_all_callbacks_and_observers_except_validate.rb +9 -0
- data/lib/copyable/declarations/main.rb +32 -0
- data/lib/copyable/exceptions.rb +10 -0
- data/lib/copyable/model_hooks.rb +40 -0
- data/lib/copyable/option_checker.rb +23 -0
- data/lib/copyable/railtie.rb +9 -0
- data/lib/copyable/saver.rb +19 -0
- data/lib/copyable/single_copy_enforcer.rb +68 -0
- data/lib/copyable/syntax_checking/association_checker.rb +41 -0
- data/lib/copyable/syntax_checking/column_checker.rb +43 -0
- data/lib/copyable/syntax_checking/completeness_checker.rb +27 -0
- data/lib/copyable/syntax_checking/declaration_checker.rb +26 -0
- data/lib/copyable/syntax_checking/declaration_stubber.rb +18 -0
- data/lib/copyable/syntax_checking/syntax_checker.rb +15 -0
- data/lib/copyable/version.rb +3 -0
- data/lib/tasks/copyable.rake +55 -0
- data/spec/config_spec.rb +132 -0
- data/spec/copy_registry_spec.rb +55 -0
- data/spec/copyable_after_copy_spec.rb +28 -0
- data/spec/copyable_associations_spec.rb +366 -0
- data/spec/copyable_columns_spec.rb +116 -0
- data/spec/copyable_spec.rb +7 -0
- data/spec/create_copy_spec.rb +136 -0
- data/spec/deep_structure_copy_spec.rb +169 -0
- data/spec/helper/copyable_spec_helper.rb +15 -0
- data/spec/helper/test_models.rb +136 -0
- data/spec/helper/test_tables.rb +135 -0
- data/spec/model_hooks_spec.rb +66 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/stress_test_spec.rb +261 -0
- data/spec/syntax_checking/association_checker_spec.rb +80 -0
- data/spec/syntax_checking/column_checker_spec.rb +49 -0
- data/spec/syntax_checking/declaration_checker_spec.rb +58 -0
- data/spec/syntax_checking_spec.rb +258 -0
- data/spec/transaction_spec.rb +78 -0
- metadata +200 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require_relative '../helper/copyable_spec_helper'
|
2
|
+
|
3
|
+
describe Copyable::AssociationChecker do
|
4
|
+
|
5
|
+
it 'should not throw an error if all associations are present' do
|
6
|
+
block = Proc.new do
|
7
|
+
associations({
|
8
|
+
copyable_pets: :copy,
|
9
|
+
})
|
10
|
+
end
|
11
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePetFood)
|
12
|
+
expect { association_checker.verify!(block) }.to_not raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should throw an error if unrecognized associations are present' do
|
16
|
+
block = Proc.new do
|
17
|
+
associations({
|
18
|
+
copyable_pets: :copy,
|
19
|
+
what_is_this: :copy,
|
20
|
+
})
|
21
|
+
end
|
22
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePetFood)
|
23
|
+
expect { association_checker.verify!(block) }.to raise_error(Copyable::AssociationError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should not require "has many through" or "has one through" relationships to be listed' do
|
27
|
+
block = Proc.new do
|
28
|
+
associations({
|
29
|
+
copyable_toys: :copy,
|
30
|
+
copyable_pet_tag: :copy,
|
31
|
+
copyable_pet_profile: :copy,
|
32
|
+
copyable_pet_foods: :copy,
|
33
|
+
copyable_pet_sitting_patronages: :copy,
|
34
|
+
})
|
35
|
+
end
|
36
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePet)
|
37
|
+
expect { association_checker.verify!(block) }.to_not raise_error
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should not require "belongs to" relationships to be listed' do
|
41
|
+
block = Proc.new do
|
42
|
+
associations({
|
43
|
+
copyable_address: :copy,
|
44
|
+
})
|
45
|
+
end
|
46
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePetProfile)
|
47
|
+
expect { association_checker.verify!(block) }.to_not raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should require "has one" relationships to be listed' do
|
51
|
+
block = Proc.new do
|
52
|
+
associations({
|
53
|
+
# MISSING copyable_address: :copy,
|
54
|
+
})
|
55
|
+
end
|
56
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePetProfile)
|
57
|
+
expect { association_checker.verify!(block) }.to raise_error(Copyable::AssociationError)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should require "has many" relationships to be listed' do
|
61
|
+
block = Proc.new do
|
62
|
+
associations({
|
63
|
+
# MISSING copyable_pet_sitting_patronages: :copy,
|
64
|
+
})
|
65
|
+
end
|
66
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePetSitter)
|
67
|
+
expect { association_checker.verify!(block) }.to raise_error(Copyable::AssociationError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should require "has and belongs to many" relationships to be listed' do
|
71
|
+
block = Proc.new do
|
72
|
+
associations({
|
73
|
+
# MISSING copyable_pets: :copy,
|
74
|
+
})
|
75
|
+
end
|
76
|
+
association_checker = Copyable::AssociationChecker.new(CopyablePetFood)
|
77
|
+
expect { association_checker.verify!(block) }.to raise_error(Copyable::AssociationError)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative '../helper/copyable_spec_helper'
|
2
|
+
|
3
|
+
describe Copyable::ColumnChecker do
|
4
|
+
|
5
|
+
it 'should not throw an error if all columns are present' do
|
6
|
+
block = Proc.new do
|
7
|
+
columns({
|
8
|
+
name: :copy,
|
9
|
+
kind: :copy,
|
10
|
+
birth_year: :copy,
|
11
|
+
})
|
12
|
+
end
|
13
|
+
column_checker = Copyable::ColumnChecker.new(CopyablePet)
|
14
|
+
expect { column_checker.verify!(block) }.to_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should throw an error if columns are empty' do
|
18
|
+
block = Proc.new do
|
19
|
+
columns({})
|
20
|
+
end
|
21
|
+
column_checker = Copyable::ColumnChecker.new(CopyablePet)
|
22
|
+
expect { column_checker.verify!(block) }.to raise_error(Copyable::ColumnError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should throw an error if a column is missing' do
|
26
|
+
block = Proc.new do
|
27
|
+
columns({
|
28
|
+
name: :copy,
|
29
|
+
birth_year: :copy,
|
30
|
+
})
|
31
|
+
end
|
32
|
+
column_checker = Copyable::ColumnChecker.new(CopyablePet)
|
33
|
+
expect { column_checker.verify!(block) }.to raise_error(Copyable::ColumnError)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should throw an error if an unrecognized column is present' do
|
37
|
+
block = Proc.new do
|
38
|
+
columns({
|
39
|
+
name: :copy,
|
40
|
+
kind: :copy,
|
41
|
+
intruder: :copy,
|
42
|
+
birth_year: :copy,
|
43
|
+
})
|
44
|
+
end
|
45
|
+
column_checker = Copyable::ColumnChecker.new(CopyablePet)
|
46
|
+
expect { column_checker.verify!(block) }.to raise_error(Copyable::ColumnError)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../helper/copyable_spec_helper'
|
2
|
+
|
3
|
+
describe Copyable::DeclarationChecker do
|
4
|
+
|
5
|
+
it 'should throw an error if there are no declarations' do
|
6
|
+
block = Proc.new {}
|
7
|
+
expect { subject.verify!(block) }.to raise_error(Copyable::DeclarationError)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should not throw an error if all required declarations are present' do
|
11
|
+
block = Proc.new do
|
12
|
+
disable_all_callbacks_and_observers_except_validate
|
13
|
+
columns
|
14
|
+
associations
|
15
|
+
end
|
16
|
+
expect { subject.verify!(block) }.to_not raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should not throw an error if all declarations are present' do
|
20
|
+
block = Proc.new do
|
21
|
+
disable_all_callbacks_and_observers_except_validate
|
22
|
+
columns
|
23
|
+
associations
|
24
|
+
after_copy
|
25
|
+
end
|
26
|
+
expect { subject.verify!(block) }.to_not raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should throw an error if an unknown declaration is present' do
|
30
|
+
block = Proc.new do
|
31
|
+
disable_all_callbacks_and_observers_except_validate
|
32
|
+
columns
|
33
|
+
unknown
|
34
|
+
associations
|
35
|
+
after_copy
|
36
|
+
end
|
37
|
+
expect { subject.verify!(block) }.to raise_error(Copyable::DeclarationError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should throw an error if a required declaration is missing' do
|
41
|
+
block = Proc.new do
|
42
|
+
columns
|
43
|
+
associations
|
44
|
+
end
|
45
|
+
expect { subject.verify!(block) }.to raise_error(Copyable::DeclarationError)
|
46
|
+
block = Proc.new do
|
47
|
+
disable_all_callbacks_and_observers_except_validate
|
48
|
+
associations
|
49
|
+
end
|
50
|
+
expect { subject.verify!(block) }.to raise_error(Copyable::DeclarationError)
|
51
|
+
block = Proc.new do
|
52
|
+
disable_all_callbacks_and_observers_except_validate
|
53
|
+
columns
|
54
|
+
end
|
55
|
+
expect { subject.verify!(block) }.to raise_error(Copyable::DeclarationError)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require_relative 'helper/copyable_spec_helper'
|
2
|
+
|
3
|
+
# Even though we have good specs that test the syntax checker classes
|
4
|
+
# individually, we still need the specs in this file to make sure the syntax
|
5
|
+
# checking is hooked up properly to the copyable declaration.
|
6
|
+
|
7
|
+
describe 'syntax checking' do
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
#*****************************************************************************
|
12
|
+
# COPYABLE
|
13
|
+
|
14
|
+
context 'copyable' do
|
15
|
+
it 'should throw an error when passed no block' do
|
16
|
+
model_definition = lambda do
|
17
|
+
undefine_copyable_in CopyableCoin
|
18
|
+
class CopyableCoin < ActiveRecord::Base
|
19
|
+
copyable
|
20
|
+
end
|
21
|
+
end
|
22
|
+
expect(model_definition).to raise_error(Copyable::CopyableError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should throw an error when passed an empty block' do
|
26
|
+
model_definition = lambda do
|
27
|
+
undefine_copyable_in CopyableCoin
|
28
|
+
class CopyableCoin < ActiveRecord::Base
|
29
|
+
copyable do
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
expect(model_definition).to raise_error(Copyable::DeclarationError)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should not throw an error when all required declarations are present' do
|
37
|
+
model_definition = lambda do
|
38
|
+
undefine_copyable_in CopyableCoin
|
39
|
+
class CopyableCoin < ActiveRecord::Base
|
40
|
+
copyable do
|
41
|
+
disable_all_callbacks_and_observers_except_validate
|
42
|
+
columns({
|
43
|
+
kind: :copy,
|
44
|
+
year: :copy,
|
45
|
+
})
|
46
|
+
associations({
|
47
|
+
})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
expect(model_definition).to_not raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should not throw an error when all declarations are present' do
|
55
|
+
model_definition = lambda do
|
56
|
+
undefine_copyable_in CopyableCoin
|
57
|
+
class CopyableCoin < ActiveRecord::Base
|
58
|
+
copyable do
|
59
|
+
disable_all_callbacks_and_observers_except_validate
|
60
|
+
columns({
|
61
|
+
kind: :copy,
|
62
|
+
year: :copy,
|
63
|
+
})
|
64
|
+
associations({
|
65
|
+
})
|
66
|
+
after_copy do |original_model, new_model|
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
expect(model_definition).to_not raise_error
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should throw an error when an unknown declaration is present' do
|
75
|
+
model_definition = lambda do
|
76
|
+
undefine_copyable_in CopyableCoin
|
77
|
+
class CopyableCoin < ActiveRecord::Base
|
78
|
+
copyable do
|
79
|
+
disable_all_callbacks_and_observers_except_validate
|
80
|
+
columns({
|
81
|
+
kind: :copy,
|
82
|
+
year: :copy,
|
83
|
+
})
|
84
|
+
associations({
|
85
|
+
})
|
86
|
+
what_the_heck_is_this_doing_here
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
expect(model_definition).to raise_error(Copyable::DeclarationError)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should throw an error if a required declaration is missing' do
|
94
|
+
model_definition = lambda do
|
95
|
+
undefine_copyable_in CopyableCoin
|
96
|
+
class CopyableCoin < ActiveRecord::Base
|
97
|
+
copyable do
|
98
|
+
# MISSING disable_all_callbacks_and_observers_except_validate
|
99
|
+
columns({
|
100
|
+
kind: :copy,
|
101
|
+
year: :copy,
|
102
|
+
})
|
103
|
+
associations({
|
104
|
+
})
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
expect(model_definition).to raise_error(Copyable::DeclarationError)
|
109
|
+
model_definition = lambda do
|
110
|
+
undefine_copyable_in CopyableCoin
|
111
|
+
class CopyableCoin < ActiveRecord::Base
|
112
|
+
copyable do
|
113
|
+
disable_all_callbacks_and_observers_except_validate
|
114
|
+
# MISSING columns({
|
115
|
+
# kind: :copy,
|
116
|
+
# year: :copy,
|
117
|
+
# })
|
118
|
+
associations({
|
119
|
+
})
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
expect(model_definition).to raise_error(Copyable::DeclarationError)
|
124
|
+
model_definition = lambda do
|
125
|
+
undefine_copyable_in CopyableCoin
|
126
|
+
class CopyableCoin < ActiveRecord::Base
|
127
|
+
copyable do
|
128
|
+
disable_all_callbacks_and_observers_except_validate
|
129
|
+
columns({
|
130
|
+
kind: :copy,
|
131
|
+
year: :copy,
|
132
|
+
})
|
133
|
+
# MISSING associations({
|
134
|
+
# })
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
expect(model_definition).to raise_error(Copyable::DeclarationError)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
#*****************************************************************************
|
145
|
+
# COLUMNS
|
146
|
+
|
147
|
+
context 'copyable:columns' do
|
148
|
+
context 'when missing columns' do
|
149
|
+
before(:each) do
|
150
|
+
@model_definition = lambda do
|
151
|
+
undefine_copyable_in CopyableCoin
|
152
|
+
class CopyableCoin < ActiveRecord::Base
|
153
|
+
copyable do
|
154
|
+
disable_all_callbacks_and_observers_except_validate
|
155
|
+
columns({
|
156
|
+
kind: :copy,
|
157
|
+
})
|
158
|
+
associations({
|
159
|
+
})
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should throw an error' do
|
166
|
+
expect(@model_definition).to raise_error(Copyable::ColumnError)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'with unknown columns' do
|
171
|
+
before(:each) do
|
172
|
+
@model_definition = lambda do
|
173
|
+
undefine_copyable_in CopyableCoin
|
174
|
+
class CopyableCoin < ActiveRecord::Base
|
175
|
+
copyable do
|
176
|
+
disable_all_callbacks_and_observers_except_validate
|
177
|
+
columns({
|
178
|
+
what_is_this_column_doing_here: :copy,
|
179
|
+
kind: :copy,
|
180
|
+
year: :copy,
|
181
|
+
})
|
182
|
+
associations({
|
183
|
+
})
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should throw an error' do
|
190
|
+
expect(@model_definition).to raise_error(Copyable::ColumnError)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
#*****************************************************************************
|
198
|
+
# ASSOCIATIONS
|
199
|
+
|
200
|
+
context 'copyable:associations' do
|
201
|
+
context 'when missing associations' do
|
202
|
+
before(:each) do
|
203
|
+
@model_definition = lambda do
|
204
|
+
class CopyablePet < ActiveRecord::Base
|
205
|
+
copyable do
|
206
|
+
disable_all_callbacks_and_observers_except_validate
|
207
|
+
columns({
|
208
|
+
name: :copy,
|
209
|
+
kind: :copy,
|
210
|
+
birth_year: :copy,
|
211
|
+
})
|
212
|
+
associations({
|
213
|
+
# MISSING copyable_toys: :copy,
|
214
|
+
copyable_pet_tag: :copy,
|
215
|
+
copyable_pet_profile: :copy,
|
216
|
+
copyable_pet_foods: :copy,
|
217
|
+
copyable_pet_sitting_patronages: :copy,
|
218
|
+
})
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'should throw an error' do
|
225
|
+
expect(@model_definition).to raise_error(Copyable::AssociationError)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'with unknown associations' do
|
230
|
+
before(:each) do
|
231
|
+
@model_definition = lambda do
|
232
|
+
class CopyablePet < ActiveRecord::Base
|
233
|
+
copyable do
|
234
|
+
disable_all_callbacks_and_observers_except_validate
|
235
|
+
columns({
|
236
|
+
name: :copy,
|
237
|
+
kind: :copy,
|
238
|
+
birth_year: :copy,
|
239
|
+
})
|
240
|
+
associations({
|
241
|
+
this_assoc_should_not_be_here: :copy,
|
242
|
+
copyable_toys: :copy,
|
243
|
+
copyable_pet_tag: :copy,
|
244
|
+
copyable_pet_profile: :copy,
|
245
|
+
copyable_pet_foods: :copy,
|
246
|
+
copyable_pet_sitting_patronages: :copy,
|
247
|
+
})
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should throw an error' do
|
254
|
+
expect(@model_definition).to raise_error(Copyable::AssociationError)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative 'helper/copyable_spec_helper'
|
2
|
+
|
3
|
+
describe 'failing' do
|
4
|
+
before(:each) do
|
5
|
+
|
6
|
+
#***************************************************************************
|
7
|
+
# Define all of the copyable declarations.
|
8
|
+
|
9
|
+
undefine_copyable_in CopyableVehicle
|
10
|
+
class CopyableVehicle < ActiveRecord::Base
|
11
|
+
copyable do
|
12
|
+
disable_all_callbacks_and_observers_except_validate
|
13
|
+
columns({
|
14
|
+
name: :copy,
|
15
|
+
copyable_owner_id: :copy,
|
16
|
+
})
|
17
|
+
associations({
|
18
|
+
copyable_amenities: :copy,
|
19
|
+
})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
undefine_copyable_in CopyableAmenity
|
24
|
+
class CopyableAmenity < ActiveRecord::Base
|
25
|
+
copyable do
|
26
|
+
disable_all_callbacks_and_observers_except_validate
|
27
|
+
columns({
|
28
|
+
name: :copy,
|
29
|
+
copyable_vehicle_id: :copy,
|
30
|
+
copyable_owner_id: :copy,
|
31
|
+
})
|
32
|
+
associations({
|
33
|
+
copyable_warranty: :copy,
|
34
|
+
})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
undefine_copyable_in CopyableWarranty
|
39
|
+
class CopyableWarranty < ActiveRecord::Base
|
40
|
+
copyable do
|
41
|
+
disable_all_callbacks_and_observers_except_validate
|
42
|
+
columns({
|
43
|
+
name: lambda { |orig| raise Copyable::CopyableError.new("intentional error") },
|
44
|
+
copyable_amenity_id: :copy,
|
45
|
+
})
|
46
|
+
associations({
|
47
|
+
})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#***************************************************************************
|
52
|
+
# Create the models.
|
53
|
+
|
54
|
+
@vehicle1 = CopyableVehicle.create!(name: 'Corvette')
|
55
|
+
@amenity1 = CopyableAmenity.create!(name: 'moon roof', copyable_vehicle: @vehicle1)
|
56
|
+
@warranty1 = CopyableWarranty.create!(name: 'moon roof warranty', copyable_amenity: @amenity1)
|
57
|
+
@amenity2 = CopyableAmenity.create!(name: 'twitter', copyable_vehicle: @vehicle1)
|
58
|
+
@warranty2 = CopyableWarranty.create!(name: 'twitter warranty', copyable_amenity: @amenity2)
|
59
|
+
@amenity3 = CopyableAmenity.create!(name: 'jazz', copyable_vehicle: @vehicle1)
|
60
|
+
@warranty3 = CopyableWarranty.create!(name: 'jazz warranty', copyable_amenity: @amenity3)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should be transactional' do
|
64
|
+
expect(CopyableVehicle.count).to eq(1)
|
65
|
+
expect(CopyableAmenity.count).to eq(3)
|
66
|
+
expect(CopyableWarranty.count).to eq(3)
|
67
|
+
begin
|
68
|
+
@vehicle2 = @vehicle1.create_copy!
|
69
|
+
rescue Copyable::CopyableError
|
70
|
+
# swallow the intentional error
|
71
|
+
end
|
72
|
+
# transaction rollback should prevent any new records from actually
|
73
|
+
# being generated
|
74
|
+
expect(CopyableVehicle.count).to eq(1)
|
75
|
+
expect(CopyableAmenity.count).to eq(3)
|
76
|
+
expect(CopyableWarranty.count).to eq(3)
|
77
|
+
end
|
78
|
+
end
|