amoeba 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,6 +16,11 @@ module Amoeba
16
16
  @config
17
17
  end
18
18
 
19
+ def reset_amoeba(&block)
20
+ @config_block = block if block_given?
21
+ @config = Amoeba::Config.new(self)
22
+ end
23
+
19
24
  def amoeba_block
20
25
  @config_block
21
26
  end
@@ -9,10 +9,11 @@ module Amoeba
9
9
  def_delegators :old_object, :_parent_amoeba, :_amoeba_settings,
10
10
  :_parent_amoeba_settings
11
11
 
12
- def_delegators :object_klass, :amoeba, :fresh_amoeba
12
+ def_delegators :object_klass, :amoeba, :fresh_amoeba, :reset_amoeba
13
13
 
14
14
  def initialize(object, options = {})
15
- @old_object, @options = object, options
15
+ @old_object = object
16
+ @options = options
16
17
  @object_klass = @old_object.class
17
18
  inherit_parent_settings
18
19
  @new_object = object.__send__(amoeba.dup_method)
@@ -40,12 +41,13 @@ module Amoeba
40
41
  end
41
42
 
42
43
  def inherit_submissive_parent_settings
43
- fresh_amoeba(&_parent_amoeba_settings)
44
+ reset_amoeba(&_amoeba_settings)
45
+ amoeba(&_parent_amoeba_settings)
44
46
  amoeba(&_amoeba_settings)
45
47
  end
46
48
 
47
49
  def inherit_parent_settings
48
- return if amoeba.enabled || !_parent_amoeba.inherit
50
+ return if !_parent_amoeba.inherit
49
51
  return unless %w(strict relaxed submissive).include?(parenting_style.to_s)
50
52
  __send__("inherit_#{parenting_style}_parent_settings".to_sym)
51
53
  end
@@ -64,19 +66,21 @@ module Amoeba
64
66
  # table from copying so we don't end up with the new
65
67
  # and old children on the copy
66
68
  return unless association.macro == :has_many ||
67
- association.is_a?(::ActiveRecord::Reflection::ThroughReflection)
69
+ association.is_a?(::ActiveRecord::Reflection::ThroughReflection)
68
70
  amoeba.exclude_association(association.options[:through])
69
71
  end
70
72
 
71
73
  def follow_only_includes
72
- amoeba.includes.each do |include|
74
+ amoeba.includes.each do |include, options|
75
+ next if options[:if] && !@old_object.send(options[:if])
73
76
  follow_association(include, @object_klass.reflect_on_association(include))
74
77
  end
75
78
  end
76
79
 
77
80
  def follow_all_except_excludes
78
81
  @object_klass.reflections.each do |name, association|
79
- next if amoeba.excludes.include?(name.to_sym)
82
+ exclude = amoeba.excludes[name.to_sym]
83
+ next if exclude && (exclude.blank? || @old_object.send(exclude[:if]))
80
84
  follow_association(name, association)
81
85
  end
82
86
  end
@@ -88,9 +92,9 @@ module Amoeba
88
92
  end
89
93
 
90
94
  def apply_associations
91
- if amoeba.includes.size > 0
95
+ if amoeba.includes.present?
92
96
  follow_only_includes
93
- elsif amoeba.excludes.size > 0
97
+ elsif amoeba.excludes.present?
94
98
  follow_all_except_excludes
95
99
  else
96
100
  follow_all
@@ -110,7 +114,7 @@ module Amoeba
110
114
 
111
115
  def process_overrides
112
116
  amoeba.overrides.each do |block|
113
- block.call(@new_object, @new_object)
117
+ block.call(@old_object, @new_object)
114
118
  end
115
119
  end
116
120
 
@@ -124,7 +128,7 @@ module Amoeba
124
128
  def process_coercions
125
129
  # prepend any extra strings to indicate uniqueness of the new record(s)
126
130
  amoeba.coercions.each do |field, coercion|
127
- @new_object[field] = "#{coercion}"
131
+ @new_object[field] = coercion.to_s
128
132
  end
129
133
  end
130
134
 
@@ -8,8 +8,8 @@ module Amoeba
8
8
  raised: false,
9
9
  dup_method: :dup,
10
10
  remap_method: nil,
11
- includes: [],
12
- excludes: [],
11
+ includes: {},
12
+ excludes: {},
13
13
  clones: [],
14
14
  customizations: [],
15
15
  overrides: [],
@@ -40,7 +40,7 @@ module Amoeba
40
40
  DEFAULTS.freeze
41
41
 
42
42
  DEFAULTS.each do |key, value|
43
- value.freeze
43
+ value.freeze if value.is_a?(Array) || value.is_a?(Hash)
44
44
  class_eval <<-EOS, __FILE__, __LINE__ + 1
45
45
  def #{key} # def enabled
46
46
  @config[:#{key}] # @config[:enabled]
@@ -69,15 +69,15 @@ module Amoeba
69
69
 
70
70
  def propagate(style = :submissive)
71
71
  @config[:parenting] ||= style
72
- @config[:inherit] = true
72
+ @config[:inherit] = true
73
73
  end
74
74
 
75
75
  def push_value_to_array(value, key)
76
76
  res = @config[key]
77
77
  if value.is_a?(::Array)
78
78
  res = value
79
- else
80
- res << value if value
79
+ elsif value
80
+ res << value
81
81
  end
82
82
  @config[key] = res.uniq
83
83
  end
@@ -107,37 +107,45 @@ module Amoeba
107
107
  @config[config_key][key] = val if val || (!val.nil? && config_key == :coercions)
108
108
  end
109
109
 
110
- def include_association(value = nil)
111
- @config[:enabled] = true
112
- @config[:excludes] = []
113
- push_value_to_array(value, :includes)
110
+ def include_association(value = nil, options = {})
111
+ enable
112
+ @config[:excludes] = {}
113
+ push_value_to_hash({ value => options }, :includes)
114
+ end
115
+
116
+ def include_associations(*values)
117
+ values.flatten.each { |v| include_association(v) }
114
118
  end
115
119
 
116
- # TODO remove this method in v3.0.0
120
+ # TODO: remove this method in v3.0.0
117
121
  def include_field(value = nil)
118
- warn "include_field is deprecated and will be removed in version 3.0.0; please use include_association instead"
122
+ warn 'include_field is deprecated and will be removed in version 3.0.0; please use include_association instead'
119
123
  include_association(value)
120
124
  end
121
125
 
122
- def exclude_association(value = nil)
123
- @config[:enabled] = true
124
- @config[:includes] = []
125
- push_value_to_array(value, :excludes)
126
+ def exclude_association(value = nil, options = {})
127
+ enable
128
+ @config[:includes] = {}
129
+ push_value_to_hash({ value => options }, :excludes)
126
130
  end
127
131
 
128
- # TODO remove this method in v3.0.0
132
+ def exclude_associations(*values)
133
+ values.flatten.each { |v| exclude_association(v) }
134
+ end
135
+
136
+ # TODO: remove this method in v3.0.0
129
137
  def exclude_field(value = nil)
130
- warn "exclude_field is deprecated and will be removed in version 3.0.0; please use exclude_association instead"
138
+ warn 'exclude_field is deprecated and will be removed in version 3.0.0; please use exclude_association instead'
131
139
  exclude_association(value)
132
140
  end
133
141
 
134
142
  def clone(value = nil)
135
- @config[:enabled] = true
143
+ enable
136
144
  push_value_to_array(value, :clones)
137
145
  end
138
146
 
139
147
  def recognize(value = nil)
140
- @config[:enabled] = true
148
+ enable
141
149
  push_value_to_array(value, :known_macros)
142
150
  end
143
151
 
@@ -1,3 +1,3 @@
1
1
  module Amoeba
2
- VERSION = '3.0.0'
2
+ VERSION = '3.1.0'
3
3
  end
@@ -5,6 +5,9 @@ describe 'amoeba' do
5
5
  before :each do
6
6
  require ::File.dirname(__FILE__) + '/../support/data.rb'
7
7
  end
8
+
9
+ let(:first_product) { Product.find(1) }
10
+
8
11
  it 'duplicates associated child records' do
9
12
  # Posts {{{
10
13
  old_post = ::Post.find(1)
@@ -29,18 +32,16 @@ describe 'amoeba' do
29
32
  start_postconfig_count = PostConfig.all.count
30
33
  start_postwidget_count = PostWidget.all.count
31
34
  start_superkitten_count = Superkitten.all.count
32
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS tag_count FROM posts_tags')
33
- start_posttag_count = rs['tag_count']
34
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS note_count FROM notes_posts')
35
- start_postnote_count = rs['note_count']
35
+ start_posttag_count = Post.tag_count
36
+ start_postnote_count = Post.note_count
36
37
 
37
38
  expect(new_post.save!).to be_truthy
38
39
  expect(new_post.title).to eq("Copy of #{old_post.title}")
39
40
 
40
- end_account_count = Account.all.count
41
- end_history_count = History.all.count
42
- end_cat_count = Category.all.count
43
- end_supercat_count = Supercat.all.count
41
+ end_account_count = Account.count
42
+ end_history_count = History.count
43
+ end_cat_count = Category.count
44
+ end_supercat_count = Supercat.count
44
45
  end_tag_count = Tag.all.count
45
46
  end_note_count = Note.all.count
46
47
  end_widget_count = Widget.all.count
@@ -50,10 +51,8 @@ describe 'amoeba' do
50
51
  end_postconfig_count = PostConfig.all.count
51
52
  end_postwidget_count = PostWidget.all.count
52
53
  end_superkitten_count = Superkitten.all.count
53
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS tag_count FROM posts_tags')
54
- end_posttag_count = rs['tag_count']
55
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS note_count FROM notes_posts')
56
- end_postnote_count = rs['note_count']
54
+ end_posttag_count = Post.tag_count
55
+ end_postnote_count = Post.note_count
57
56
 
58
57
  expect(end_tag_count).to eq(start_tag_count)
59
58
  expect(end_cat_count).to eq(start_cat_count)
@@ -71,9 +70,9 @@ describe 'amoeba' do
71
70
  expect(end_postnote_count).to eq(start_postnote_count * 2)
72
71
  expect(end_superkitten_count).to eq(start_superkitten_count * 2)
73
72
 
74
- expect(new_post.supercats.map(&:ramblings).include?('Copy of zomg')).to be true
73
+ expect(new_post.supercats.map(&:ramblings)).to include('Copy of zomg')
75
74
  expect(new_post.supercats.map(&:other_ramblings).uniq.length).to eq(1)
76
- expect(new_post.supercats.map(&:other_ramblings).uniq.include?('La la la')).to be true
75
+ expect(new_post.supercats.map(&:other_ramblings).uniq).to include('La la la')
77
76
  expect(new_post.contents).to eq("Here's a copy: #{old_post.contents.gsub(/dog/, 'cat')} (copied version)")
78
77
  expect(new_post.comments.length).to eq(5)
79
78
  expect(new_post.comments.select { |c| c.nerf == 'ratatat' && c.contents.nil? }.length).to eq(1)
@@ -82,7 +81,7 @@ describe 'amoeba' do
82
81
  expect(new_post.comments.select { |c| c.nerf == 'bonkers' && c.contents.nil? }.length).to eq(1)
83
82
 
84
83
  new_post.widgets.map(&:id).each do |id|
85
- expect(old_post.widgets.map(&:id).include?(id)).not_to be true
84
+ expect(old_post.widgets.map(&:id)).not_to include(id)
86
85
  end
87
86
 
88
87
  expect(new_post.custom_things.length).to eq(3)
@@ -94,7 +93,7 @@ describe 'amoeba' do
94
93
  old_author = Author.find(1)
95
94
  new_author = old_author.amoeba_dup
96
95
  new_author.save!
97
- expect(new_author.errors.messages.length).to eq(0)
96
+ expect(new_author.errors.messages).to be_empty
98
97
  expect(new_author.posts.first.custom_things.length).to eq(3)
99
98
  expect(new_author.posts.first.custom_things.select { |ct| ct.value == [] }.length).to eq(1)
100
99
  expect(new_author.posts.first.custom_things.select { |ct| ct.value == [1, 2] }.length).to eq(1)
@@ -102,24 +101,20 @@ describe 'amoeba' do
102
101
  # }}}
103
102
  # Products {{{
104
103
  # Base Class {{{
105
- old_product = Product.find(1)
106
104
 
107
- start_image_count = Image.where(product_id: old_product.id).count
105
+ start_image_count = first_product.images.count
108
106
  start_section_count = Section.all.length
109
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', old_product.id)
110
- start_prodsection_count = rs['section_count']
107
+ start_prodsection_count = first_product.section_count
111
108
 
112
- new_product = old_product.amoeba_dup
109
+ new_product = first_product.amoeba_dup
113
110
  new_product.save
114
- expect(new_product.errors.messages.length).to eq(0)
111
+ expect(new_product.errors.messages).to be_empty
115
112
 
116
- end_image_count = Image.where(product_id: old_product.id).count
117
- end_newimage_count = Image.where(product_id: new_product.id).count
113
+ end_image_count = first_product.images.count
114
+ end_newimage_count = new_product.images.count
118
115
  end_section_count = Section.all.length
119
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', 1)
120
- end_prodsection_count = rs['section_count']
121
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', new_product.id)
122
- end_newprodsection_count = rs['section_count']
116
+ end_prodsection_count = first_product.section_count
117
+ end_newprodsection_count = new_product.section_count
123
118
 
124
119
  expect(end_image_count).to eq(start_image_count)
125
120
  expect(end_newimage_count).to eq(start_image_count)
@@ -132,22 +127,19 @@ describe 'amoeba' do
132
127
  # Shirt {{{
133
128
  old_product = Shirt.find(2)
134
129
 
135
- start_image_count = Image.where(product_id: old_product.id).count
136
- start_section_count = Section.all.length
137
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', old_product.id)
138
- start_prodsection_count = rs['section_count']
130
+ start_image_count = old_product.images.count
131
+ start_section_count = Section.count
132
+ start_prodsection_count = old_product.section_count
139
133
 
140
134
  new_product = old_product.amoeba_dup
141
135
  new_product.save
142
- expect(new_product.errors.messages.length).to eq(0)
136
+ expect(new_product.errors.messages).to be_empty
143
137
 
144
- end_image_count = Image.where(product_id: old_product.id).count
145
- end_newimage_count = Image.where(product_id: new_product.id).count
146
- end_section_count = Section.all.length
147
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', 1)
148
- end_prodsection_count = rs['section_count']
149
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', new_product.id)
150
- end_newprodsection_count = rs['section_count']
138
+ end_image_count = old_product.images.count
139
+ end_newimage_count = new_product.images.count
140
+ end_section_count = Section.count
141
+ end_prodsection_count = first_product.section_count
142
+ end_newprodsection_count = new_product.section_count
151
143
 
152
144
  expect(end_image_count).to eq(start_image_count)
153
145
  expect(end_newimage_count).to eq(start_image_count)
@@ -159,22 +151,19 @@ describe 'amoeba' do
159
151
  # Necklace {{{
160
152
  old_product = Necklace.find(3)
161
153
 
162
- start_image_count = Image.where(product_id: old_product.id).count
163
- start_section_count = Section.all.length
164
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', old_product.id)
165
- start_prodsection_count = rs['section_count']
154
+ start_image_count = old_product.images.count
155
+ start_section_count = Section.count
156
+ start_prodsection_count = old_product.section_count
166
157
 
167
158
  new_product = old_product.amoeba_dup
168
159
  new_product.save
169
- expect(new_product.errors.messages.length).to eq(0)
160
+ expect(new_product.errors.messages).to be_empty
170
161
 
171
- end_image_count = Image.where(product_id: old_product.id).count
172
- end_newimage_count = Image.where(product_id: new_product.id).count
173
- end_section_count = Section.all.length
174
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', 1)
175
- end_prodsection_count = rs['section_count']
176
- rs = ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?', new_product.id)
177
- end_newprodsection_count = rs['section_count']
162
+ end_image_count = old_product.images.count
163
+ end_newimage_count = new_product.images.count
164
+ end_section_count = Section.count
165
+ end_prodsection_count = first_product.section_count
166
+ end_newprodsection_count = new_product.section_count
178
167
 
179
168
  expect(end_image_count).to eq(start_image_count)
180
169
  expect(end_newimage_count).to eq(start_image_count)
@@ -186,23 +175,60 @@ describe 'amoeba' do
186
175
  # }}}
187
176
  end
188
177
  end
178
+
179
+ context 'use if condition in includes and excludes' do
180
+ before(:all) do
181
+ require ::File.dirname(__FILE__) + '/../support/data.rb'
182
+ end
183
+ before { ::Post.fresh_amoeba }
184
+
185
+ subject { post.amoeba_dup.save! }
186
+ let(:post) { Post.first }
187
+
188
+ it 'includes associations with truthy condition' do
189
+ ::Post.amoeba do
190
+ include_association :comments, if: :truthy?
191
+ end
192
+ expect { subject }.to change { Comment.count }.by(3)
193
+ end
194
+
195
+ it 'does not include associations with false condition' do
196
+ ::Post.amoeba do
197
+ include_association :comments, if: :falsey?
198
+ end
199
+ expect { subject }.not_to change { Comment.count }
200
+ end
201
+
202
+ it 'excludes associations with truthy condition' do
203
+ ::Post.amoeba do
204
+ exclude_association :comments, if: :truthy?
205
+ end
206
+ expect { subject }.not_to change { Comment.count }
207
+ end
208
+
209
+ it 'does not exclude associations with false condition' do
210
+ ::Post.amoeba do
211
+ exclude_association :comments, if: :falsey?
212
+ end
213
+ expect { subject }.to change { Comment.count }.by(3)
214
+ end
215
+ end
216
+
189
217
  context 'override' do
190
218
  before :each do
191
219
  ::Image.fresh_amoeba
192
220
  ::Image.amoeba do
193
- override ->(old, new) {
194
- if old.filename == 'test.jpg'
195
- new.product_id = 13
196
- end
197
- }
221
+ override ->(old, new) { new.product_id = 13 if old.filename == 'test.jpg' }
198
222
  end
199
223
  end
224
+
200
225
  it 'should override fields' do
201
226
  image = ::Image.create(filename: 'test.jpg', product_id: 12)
202
227
  image_dup = image.amoeba_dup
203
228
  expect(image_dup.save).to be_truthy
204
229
  expect(image_dup.product_id).to eq(13)
205
230
  end
231
+
206
232
  it 'should not override fields' do
207
233
  image = ::Image.create(filename: 'test2.jpg', product_id: 12)
208
234
  image_dup = image.amoeba_dup
@@ -218,17 +244,19 @@ describe 'amoeba' do
218
244
  nullify :product_id
219
245
  end
220
246
  end
247
+
248
+ let(:image) { ::Image.create(filename: 'test.jpg', product_id: 12) }
249
+ let(:image_dup) { image.amoeba_dup }
250
+
221
251
  it 'should nullify fields' do
222
- image = ::Image.create(filename: 'test.jpg', product_id: 12)
223
- image_dup = image.amoeba_dup
224
252
  expect(image_dup.save).to be_truthy
225
253
  expect(image_dup.product_id).to be_nil
226
254
  end
227
255
  end
228
256
 
229
257
  context 'strict propagate' do
230
- it 'should call #fresh_amoeba' do
231
- expect(::SuperBlackBox).to receive(:fresh_amoeba).and_call_original
258
+ it 'should call #reset_amoeba' do
259
+ expect(::SuperBlackBox).to receive(:reset_amoeba).and_call_original
232
260
  box = ::SuperBlackBox.create(title: 'Super Black Box', price: 9.99, length: 1, metal: '1')
233
261
  new_box = box.amoeba_dup
234
262
  expect(new_box.save).to be_truthy
@@ -237,12 +265,14 @@ describe 'amoeba' do
237
265
 
238
266
  context 'remapping and custom dup method' do
239
267
  let(:prototype) { ObjectPrototype.new }
268
+
240
269
  context 'through' do
241
270
  it do
242
271
  real_object = prototype.amoeba_dup
243
272
  expect(real_object).to be_a(::RealObject)
244
273
  end
245
274
  end
275
+
246
276
  context 'remapper' do
247
277
  it do
248
278
  prototype.subobject_prototypes << SubobjectPrototype.new
@@ -253,29 +283,94 @@ describe 'amoeba' do
253
283
  end
254
284
 
255
285
  context 'preprocessing fields' do
286
+ subject { super_admin.amoeba_dup }
287
+ let(:super_admin) { ::SuperAdmin.create!(email: 'user@example.com', active: true, password: 'password') }
288
+
256
289
  it 'should accept "set" to set false to attribute' do
257
- super_admin = ::SuperAdmin.create!(email: 'user@example.com', active: true, password: 'password')
258
- clone = super_admin.amoeba_dup
259
- expect(clone.active).to eq(false)
290
+ expect(subject.active).to be false
260
291
  end
292
+
261
293
  it 'should skip "prepend" if it equal to false' do
262
- super_admin = ::SuperAdmin.create!(email: 'user2@example.com', active: true, password: 'password')
263
- clone = super_admin.amoeba_dup
264
- expect(clone.password).to eq('password')
294
+ expect(subject.password).to eq('password')
265
295
  end
266
296
  end
267
297
 
268
298
  context 'inheritance' do
299
+ let(:box) { Box.create }
300
+
269
301
  it 'does not fail with a deep inheritance' do
270
- box = Box.create
271
302
  sub_sub_product = BoxSubSubProduct.create(title: 'Awesome shoes')
272
303
  another_product = BoxAnotherProduct.create(title: 'Cleaning product')
273
- sub_sub_product.box = box
274
- sub_sub_product.another_product = another_product
275
- sub_sub_product.save
304
+ sub_sub_product.update_attributes(box: box, another_product: another_product)
276
305
  expect(box.sub_products.first.another_product.title).to eq('Cleaning product')
277
306
  expect(box.amoeba_dup.sub_products.first.another_product.title).to eq('Cleaning product')
278
307
  end
279
308
  end
280
309
 
310
+ context 'inheritance extended' do
311
+ let(:stage) do
312
+ stage = CustomStage.new(title: 'My Stage', external_id: 213)
313
+ stage.listeners.build(name: 'John')
314
+ stage.listeners.build(name: 'Helen')
315
+ stage.specialists.build(name: 'Jack')
316
+ stage.custom_rules.build(description: 'Kill all humans')
317
+ stage.save!
318
+ stage
319
+ end
320
+
321
+ subject { stage.amoeba_dup }
322
+
323
+ it "contains parent association and own associations", :aggregate_failures do
324
+ subject
325
+ expect { subject.save! }.to change(Listener, :count).by(2).
326
+ and change(Specialist, :count).by(1).
327
+ and change(CustomRule, :count).by(1)
328
+
329
+ expect(subject.title).to eq 'My Stage'
330
+ expect(subject.external_id).to be_nil
331
+ expect(subject.listeners.find_by(name: 'John')).to_not be_nil
332
+ expect(subject.listeners.find_by(name: 'Helen')).to_not be_nil
333
+ expect(subject.specialists.find_by(name: 'Jack')).to_not be_nil
334
+ expect(subject.custom_rules.first.description).to eq 'Kill all humans'
335
+ end
336
+ end
337
+
338
+ context 'polymorphic' do
339
+ let(:company) { Company.find_by(name: 'ABC Industries') }
340
+ let(:new_company) { company.amoeba_dup }
341
+
342
+ it 'does not fail with a deep inheritance' do
343
+ # employee = company.employees.where(name:'Joe').first
344
+ start_company_count = Company.count
345
+ start_customer_count = Customer.count
346
+ start_employee_count = Employee.count
347
+ start_address_count = Address.count
348
+ start_photo_count = Photo.count
349
+ new_company.name = "Copy of #{new_company.name}"
350
+ new_company.save
351
+ expect(Company.count).to eq(start_company_count + 1)
352
+ expect(Customer.count).to eq(start_customer_count + 1)
353
+ expect(Employee.count).to eq(start_employee_count + 1)
354
+ expect(Address.count).to eq(start_address_count + 4)
355
+ expect(Photo.count).to eq(start_photo_count + 2)
356
+
357
+ new_company.reload # fully reload from database
358
+ new_company_employees = new_company.employees
359
+ expect(new_company_employees.count).to eq(1)
360
+ new_company_employee_joe = new_company_employees.find_by(name: 'Joe')
361
+ expect(new_company_employee_joe.photos.count).to eq(1)
362
+ expect(new_company_employee_joe.photos.first.size).to eq(12_345)
363
+ expect(new_company_employee_joe.addresses.count).to eq(2)
364
+ expect(new_company_employee_joe.addresses.where(street: '123 My Street').count).to eq(1)
365
+ expect(new_company_employee_joe.addresses.where(street: '124 My Street').count).to eq(1)
366
+ new_company_customers = new_company.customers
367
+ expect(new_company_customers.count).to eq(1)
368
+ new_company_customer_my = new_company_customers.where(email: 'my@email.address').first
369
+ expect(new_company_customer_my.photos.count).to eq(1)
370
+ expect(new_company_customer_my.photos.first.size).to eq(54_321)
371
+ expect(new_company_customer_my.addresses.count).to eq(2)
372
+ expect(new_company_customer_my.addresses.where(street: '321 My Street').count).to eq(1)
373
+ expect(new_company_customer_my.addresses.where(street: '321 My Drive').count).to eq(1)
374
+ end
375
+ end
281
376
  end