acts_as_span 0.0.5 → 1.2.0
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 +11 -3
- data/.rspec +2 -0
- data/.tool-versions +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +0 -3
- data/README.rdoc +4 -16
- data/Rakefile +5 -1
- data/acts_as_span.gemspec +31 -14
- data/config/locales/en/acts_as_span.yml +15 -0
- data/lib/acts_as_span.rb +69 -98
- data/lib/acts_as_span/end_date_propagator.rb +198 -0
- data/lib/acts_as_span/no_overlap_validator.rb +86 -0
- data/lib/acts_as_span/span_instance.rb +24 -32
- data/lib/acts_as_span/span_instance/status.rb +12 -27
- data/lib/acts_as_span/span_instance/validations.rb +11 -53
- data/lib/acts_as_span/span_klass.rb +11 -19
- data/lib/acts_as_span/span_klass/status.rb +43 -12
- data/lib/acts_as_span/version.rb +6 -4
- data/lib/acts_as_span/within_parent_date_span_validator.rb +44 -0
- data/spec/lib/acts_as_span_spec.rb +38 -35
- data/spec/lib/delegation_spec.rb +45 -78
- data/spec/lib/end_date_propagator_spec.rb +319 -0
- data/spec/lib/no_overlap_validator_spec.rb +129 -0
- data/spec/lib/span_instance/named_scopes_on_spec.rb +193 -193
- data/spec/lib/span_instance/named_scopes_spec.rb +193 -191
- data/spec/lib/span_instance/overlap_spec.rb +193 -253
- data/spec/lib/span_instance/status_spec.rb +22 -35
- data/spec/lib/span_instance/validations_spec.rb +8 -44
- data/spec/lib/span_instance_spec.rb +17 -30
- data/spec/lib/span_klass/status_spec.rb +38 -0
- data/spec/lib/within_parent_date_span_validator_spec.rb +126 -0
- data/spec/spec_helper.rb +19 -6
- data/spec/spec_models.rb +226 -0
- metadata +167 -61
- data/Gemfile.lock +0 -47
- data/lib/acts_as_span/span_instance/overlap.rb +0 -17
- data/lib/acts_as_span/span_klass/overlap.rb +0 -21
- data/spec/lib/negative_spec.rb +0 -30
- data/spec/spec.opts +0 -1
@@ -1,64 +1,67 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe "acts_as_span" do
|
4
|
-
|
5
|
-
|
6
|
-
acts_as_span
|
7
|
-
|
3
|
+
RSpec.describe "acts_as_span" do
|
4
|
+
it 'raises an ArgumentError when unsupported arguments are passed' do
|
5
|
+
expect do
|
6
|
+
SpannableModel.acts_as_span(
|
7
|
+
start_field: :starting_date,
|
8
|
+
end_field: :ending_date,
|
9
|
+
span_overlap_scope: [:unique_by_date_range]
|
10
|
+
)
|
11
|
+
end.to raise_error(
|
12
|
+
ArgumentError, "Unsupported option(s): 'span_overlap_scope'"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "doesn't raise an ArgumentError when valid arguments are passed" do
|
17
|
+
expect do
|
18
|
+
SpannableModel.acts_as_span(
|
19
|
+
start_field: :starting_date,
|
20
|
+
end_field: :ending_date
|
21
|
+
)
|
22
|
+
end.not_to raise_error
|
8
23
|
end
|
9
|
-
|
24
|
+
|
10
25
|
context "ClassMethods" do
|
11
|
-
it "should return true for acts_as_span?" do
|
12
|
-
SpanModel.acts_as_span?.should be_true
|
13
|
-
end
|
14
|
-
|
15
26
|
it "should have 1 acts_as_span_definition" do
|
16
|
-
SpanModel.
|
27
|
+
expect(SpanModel.acts_as_span_definitions.size).to eq(1)
|
17
28
|
end
|
18
|
-
|
29
|
+
|
19
30
|
it "should set default options for acts_as_span_definition" do
|
20
31
|
span_definition = SpanModel.acts_as_span_definitions[:default]
|
21
|
-
|
22
|
-
span_definition.
|
23
|
-
span_definition.
|
24
|
-
span_definition.
|
25
|
-
span_definition.
|
26
|
-
span_definition.exclude_end.should be_false
|
27
|
-
span_definition.span_overlap_scope.should be_nil
|
28
|
-
span_definition.span_overlap_count.should be_nil
|
29
|
-
span_definition.name.should == :default
|
32
|
+
|
33
|
+
expect(span_definition.start_field).to eq(:start_date)
|
34
|
+
expect(span_definition.end_field).to eq(:end_date)
|
35
|
+
expect(span_definition.exclude_end).to be_falsey
|
36
|
+
expect(span_definition.name).to eq(:default)
|
30
37
|
end
|
31
|
-
|
38
|
+
|
32
39
|
it "should return a SpanKlass w/ span" do
|
33
|
-
SpanModel.span.
|
40
|
+
expect(SpanModel.span).to be_instance_of(ActsAsSpan::SpanKlass)
|
34
41
|
end
|
35
42
|
|
36
43
|
it "should return a SpanKlass w/ span_for(:default)" do
|
37
|
-
SpanModel.span_for(:default).
|
44
|
+
expect(SpanModel.span_for(:default)).to be_instance_of(ActsAsSpan::SpanKlass)
|
38
45
|
end
|
39
|
-
|
46
|
+
|
40
47
|
it "should have (1) spans" do
|
41
|
-
SpanModel.spans.
|
48
|
+
expect(SpanModel.spans.size).to eq(1)
|
42
49
|
end
|
43
50
|
end
|
44
|
-
|
51
|
+
|
45
52
|
context "InstanceMethods" do
|
46
53
|
let(:span_model) { SpanModel.new }
|
47
|
-
|
48
|
-
it "should return true for acts_as_span?" do
|
49
|
-
span_model.acts_as_span?.should be_true
|
50
|
-
end
|
51
54
|
|
52
55
|
it "should return a SpanInstance w/ span" do
|
53
|
-
span_model.span.
|
56
|
+
expect(span_model.span).to be_instance_of(ActsAsSpan::SpanInstance)
|
54
57
|
end
|
55
58
|
|
56
59
|
it "should return a SpanInstance w/ span_for(:default)" do
|
57
|
-
span_model.span_for(:default).
|
60
|
+
expect(span_model.span_for(:default)).to be_instance_of(ActsAsSpan::SpanInstance)
|
58
61
|
end
|
59
|
-
|
62
|
+
|
60
63
|
it "should have (1) spans" do
|
61
|
-
span_model.spans.
|
64
|
+
expect(span_model.spans.size).to eq(1)
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end
|
data/spec/lib/delegation_spec.rb
CHANGED
@@ -1,128 +1,95 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe "Span" do
|
4
|
-
|
5
|
-
build_model :span_model do
|
6
|
-
date :start_date
|
7
|
-
date :end_date
|
8
|
-
|
9
|
-
acts_as_span
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:span_model) { SpanModel.new(:start_date => Date.today, :end_date => nil) }
|
3
|
+
RSpec.describe "Span" do
|
4
|
+
let(:span_model) { SpanModel.new(:start_date => Date.current, :end_date => nil) }
|
14
5
|
let(:span_klass) { SpanModel.span }
|
15
6
|
let(:span_instance) { span_model.span }
|
16
|
-
|
7
|
+
|
17
8
|
context "ClassMethods" do
|
18
9
|
it "should delegate current" do
|
19
|
-
span_klass.
|
20
|
-
|
10
|
+
expect(span_klass).to receive(:current).and_return(true)
|
11
|
+
|
21
12
|
SpanModel.current
|
22
13
|
end
|
23
|
-
|
14
|
+
|
24
15
|
it "should delegate current_on" do
|
25
|
-
span_klass.
|
26
|
-
|
16
|
+
expect(span_klass).to receive(:current_on).and_return(true)
|
17
|
+
|
27
18
|
SpanModel.current_on
|
28
19
|
end
|
29
|
-
|
20
|
+
|
30
21
|
it "should delegate future" do
|
31
|
-
span_klass.
|
32
|
-
|
22
|
+
expect(span_klass).to receive(:future).and_return(true)
|
23
|
+
|
33
24
|
SpanModel.future
|
34
25
|
end
|
35
|
-
|
26
|
+
|
36
27
|
it "should delegate future_on" do
|
37
|
-
span_klass.
|
38
|
-
|
28
|
+
expect(span_klass).to receive(:future_on).and_return(true)
|
29
|
+
|
39
30
|
SpanModel.future_on
|
40
31
|
end
|
41
|
-
|
32
|
+
|
42
33
|
it "should delegate expired" do
|
43
|
-
span_klass.
|
44
|
-
|
34
|
+
expect(span_klass).to receive(:expired).and_return(true)
|
35
|
+
|
45
36
|
SpanModel.expired
|
46
37
|
end
|
47
|
-
|
38
|
+
|
48
39
|
it "should delegate expired_on" do
|
49
|
-
span_klass.
|
50
|
-
|
40
|
+
expect(span_klass).to receive(:expired_on).and_return(true)
|
41
|
+
|
51
42
|
SpanModel.expired_on
|
52
43
|
end
|
53
44
|
end
|
54
|
-
|
45
|
+
|
55
46
|
context "InstanceMethods" do
|
56
|
-
it "should delegate close!" do
|
57
|
-
span_instance.should_receive(:close!).and_return(true)
|
58
|
-
|
59
|
-
span_model.close!
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should delegate close_on!" do
|
63
|
-
span_instance.should_receive(:close_on!).and_return(true)
|
64
|
-
|
65
|
-
span_model.close_on!
|
66
|
-
end
|
67
|
-
|
68
47
|
it "should delegate span_status" do
|
69
|
-
span_instance.
|
70
|
-
|
48
|
+
expect(span_instance).to receive(:span_status).and_return(true)
|
49
|
+
|
71
50
|
span_model.span_status
|
72
51
|
end
|
73
|
-
|
52
|
+
|
74
53
|
it "should delegate span_status_on" do
|
75
|
-
span_instance.
|
76
|
-
|
54
|
+
expect(span_instance).to receive(:span_status_on).and_return(true)
|
55
|
+
|
77
56
|
span_model.span_status_on
|
78
57
|
end
|
79
|
-
|
80
|
-
it "should delegate span_status_to_s" do
|
81
|
-
span_instance.should_receive(:span_status_to_s).and_return(true)
|
82
|
-
|
83
|
-
span_model.span_status_to_s
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should delegate span_status_to_s_on" do
|
87
|
-
span_instance.should_receive(:span_status_to_s_on).and_return(true)
|
88
|
-
|
89
|
-
span_model.span_status_to_s_on
|
90
|
-
end
|
91
|
-
|
58
|
+
|
92
59
|
it "should delegate current?" do
|
93
|
-
span_instance.
|
94
|
-
|
60
|
+
expect(span_instance).to receive(:current?).and_return(true)
|
61
|
+
|
95
62
|
span_model.current?
|
96
63
|
end
|
97
|
-
|
64
|
+
|
98
65
|
it "should delegate current_on?" do
|
99
|
-
span_instance.
|
100
|
-
|
66
|
+
expect(span_instance).to receive(:current_on?).and_return(true)
|
67
|
+
|
101
68
|
span_model.current_on?
|
102
69
|
end
|
103
|
-
|
70
|
+
|
104
71
|
it "should delegate future?" do
|
105
|
-
span_instance.
|
106
|
-
|
72
|
+
expect(span_instance).to receive(:future?).and_return(true)
|
73
|
+
|
107
74
|
span_model.future?
|
108
75
|
end
|
109
|
-
|
76
|
+
|
110
77
|
it "should delegate future_on?" do
|
111
|
-
span_instance.
|
112
|
-
|
78
|
+
expect(span_instance).to receive(:future_on?).and_return(true)
|
79
|
+
|
113
80
|
span_model.future_on?
|
114
81
|
end
|
115
|
-
|
82
|
+
|
116
83
|
it "should delegate expired?" do
|
117
|
-
span_instance.
|
118
|
-
|
84
|
+
expect(span_instance).to receive(:expired?).and_return(true)
|
85
|
+
|
119
86
|
span_model.expired?
|
120
87
|
end
|
121
|
-
|
88
|
+
|
122
89
|
it "should delegate expired_on?" do
|
123
|
-
span_instance.
|
124
|
-
|
90
|
+
expect(span_instance).to receive(:expired_on?).and_return(true)
|
91
|
+
|
125
92
|
span_model.expired_on?
|
126
93
|
end
|
127
94
|
end
|
128
|
-
end
|
95
|
+
end
|
@@ -0,0 +1,319 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActsAsSpan::EndDatePropagator do
|
4
|
+
let(:end_date_propagator) do
|
5
|
+
ActsAsSpan::EndDatePropagator.new(
|
6
|
+
base_instance, skipped_classes: skipped_classes,
|
7
|
+
include_errors: include_errors
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:base_instance) do
|
12
|
+
Base.create(end_date: initial_end_date)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:include_errors) { true }
|
16
|
+
let(:initial_end_date) { nil }
|
17
|
+
|
18
|
+
let(:other_base_instance) do
|
19
|
+
OtherBase.create(end_date: other_end_date)
|
20
|
+
end
|
21
|
+
let(:other_end_date) { nil }
|
22
|
+
|
23
|
+
let(:skipped_classes) { [] }
|
24
|
+
|
25
|
+
let!(:child_instance) do
|
26
|
+
Child.create(
|
27
|
+
base: base_instance,
|
28
|
+
emancipation_date: child_end_date
|
29
|
+
)
|
30
|
+
end
|
31
|
+
let(:child_end_date) { nil }
|
32
|
+
|
33
|
+
let!(:dog_instance) do
|
34
|
+
Dog.create(
|
35
|
+
base: base_instance,
|
36
|
+
end_date: dog_end_date
|
37
|
+
)
|
38
|
+
end
|
39
|
+
let(:dog_end_date) { nil }
|
40
|
+
|
41
|
+
let!(:bird_instance) do
|
42
|
+
Bird.create(
|
43
|
+
child: child_instance,
|
44
|
+
end_date: child_end_date
|
45
|
+
)
|
46
|
+
end
|
47
|
+
let(:bird_end_date) { nil }
|
48
|
+
|
49
|
+
let(:tale_instance) do
|
50
|
+
base_instance.tales.create(start_date: Date.current, end_date: nil)
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '@errors_cache' do
|
54
|
+
let(:base_start_date) { Date.current - 7 }
|
55
|
+
let(:initial_end_date) { nil }
|
56
|
+
let(:end_date) { Date.current }
|
57
|
+
|
58
|
+
let(:child_start_date) { base_start_date + 1 }
|
59
|
+
let!(:child_instance) do
|
60
|
+
Child.create(
|
61
|
+
base: base_instance,
|
62
|
+
date_of_birth: child_start_date,
|
63
|
+
emancipation_date: child_end_date
|
64
|
+
)
|
65
|
+
end
|
66
|
+
let(:bird_start_date) { child_start_date + 1 }
|
67
|
+
let!(:bird_instance) do
|
68
|
+
Bird.create(
|
69
|
+
child: child_instance,
|
70
|
+
start_date: bird_start_date,
|
71
|
+
end_date: bird_end_date
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
before do
|
76
|
+
base_instance.start_date = base_start_date
|
77
|
+
base_instance.save!
|
78
|
+
base_instance.end_date = end_date
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when all child records are successfully saved' do
|
82
|
+
it 'the parent record does not have any errors' do
|
83
|
+
expect(
|
84
|
+
end_date_propagator.call.errors.full_messages
|
85
|
+
).to be_empty
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when one grandchild record is not valid' do
|
90
|
+
before do
|
91
|
+
bird_instance.start_date = child_start_date - 1
|
92
|
+
bird_instance.save(validate: false)
|
93
|
+
end
|
94
|
+
it "the parent shows that grandchild's errors" do
|
95
|
+
expect(
|
96
|
+
end_date_propagator.call.errors.values.join
|
97
|
+
).to include(
|
98
|
+
I18n.t(
|
99
|
+
'not_within_parent_date_span',
|
100
|
+
parent: 'Child',
|
101
|
+
scope: %i[activerecord errors messages]
|
102
|
+
)
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when multiple child records are not valid' do
|
108
|
+
context 'when include_errors = true (default)' do
|
109
|
+
before do
|
110
|
+
child_instance.date_of_birth = base_instance.span.start_date - 1
|
111
|
+
child_instance.save(validate: false)
|
112
|
+
bird_instance.start_date = child_instance.span.start_date - 1
|
113
|
+
bird_instance.save(validate: false)
|
114
|
+
end
|
115
|
+
it "the parent gains all children's errors" do
|
116
|
+
expect(
|
117
|
+
end_date_propagator.call.errors.values.join
|
118
|
+
).to include(
|
119
|
+
I18n.t(
|
120
|
+
'not_within_parent_date_span',
|
121
|
+
parent: 'Child',
|
122
|
+
scope: %i[activerecord errors messages]
|
123
|
+
)
|
124
|
+
).and include(
|
125
|
+
I18n.t(
|
126
|
+
'not_within_parent_date_span',
|
127
|
+
parent: 'Base',
|
128
|
+
scope: %i[activerecord errors messages]
|
129
|
+
)
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when include_errors = false' do
|
135
|
+
let(:include_errors) { false }
|
136
|
+
|
137
|
+
it 'does not push any child errors' do
|
138
|
+
expect(end_date_propagator.call.errors.values).to be_empty
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '.call' do
|
145
|
+
subject(:result) do
|
146
|
+
ActsAsSpan::EndDatePropagator.call(obj, call_options)
|
147
|
+
end
|
148
|
+
let(:obj) { base_instance }
|
149
|
+
|
150
|
+
context 'when no skipped classes are passed' do
|
151
|
+
let(:call_options) { {} }
|
152
|
+
|
153
|
+
it 'forwards the correct arguments to :new' do
|
154
|
+
expect(ActsAsSpan::EndDatePropagator)
|
155
|
+
.to receive(:new).with(obj, call_options).and_call_original
|
156
|
+
expect(result).to eq(obj)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when skipped classes are passed' do
|
161
|
+
let(:call_options) { { skipped_classes: ['bungus'] } }
|
162
|
+
|
163
|
+
it 'forwards the correct arguments to :new' do
|
164
|
+
expect(ActsAsSpan::EndDatePropagator)
|
165
|
+
.to receive(:new).with(obj, call_options).and_call_original
|
166
|
+
expect(result).to eq(obj)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe '#call' do
|
172
|
+
context 'without an end_date' do
|
173
|
+
let(:object_instance) { SpannableModel.new }
|
174
|
+
|
175
|
+
it 'does not raise an error' do
|
176
|
+
expect do
|
177
|
+
ActsAsSpan::EndDatePropagator.new(object_instance).call
|
178
|
+
end.not_to raise_error
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'updates children' do
|
183
|
+
before do
|
184
|
+
base_instance
|
185
|
+
base_instance.end_date = end_date
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'base_instance.end_date nil -> !nil' do
|
189
|
+
let(:initial_end_date) { nil }
|
190
|
+
let(:end_date) { Date.current }
|
191
|
+
|
192
|
+
context 'child_end_date == initial_end_date' do
|
193
|
+
let(:child_end_date) { initial_end_date }
|
194
|
+
|
195
|
+
it 'propagates to the child_instance' do
|
196
|
+
expect{ end_date_propagator.call }.to change{
|
197
|
+
child_instance.reload.emancipation_date }
|
198
|
+
.from(child_end_date).to(base_instance.end_date)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'child_end_date >= initial_end_date' do
|
203
|
+
let(:child_end_date) { end_date + 3 }
|
204
|
+
|
205
|
+
it 'propagates to the child_instance' do
|
206
|
+
expect{ end_date_propagator.call }.to change{
|
207
|
+
child_instance.reload.emancipation_date}
|
208
|
+
.from(child_end_date).to(base_instance.end_date)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context 'child_end_date <= initial_end_date' do
|
213
|
+
let(:child_end_date) { end_date - 3 }
|
214
|
+
|
215
|
+
it 'does not propagate to the child_instance' do
|
216
|
+
expect{ end_date_propagator.call }.not_to change{
|
217
|
+
child_instance.reload.emancipation_date}
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context 'when a child cannot have its end date updated' do
|
222
|
+
before do
|
223
|
+
# add a "within parent date span" error to child
|
224
|
+
base_instance.start_date = Date.current - 1
|
225
|
+
child_instance.date_of_birth = Date.current - 2
|
226
|
+
child_instance.save(validate: false)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "the parent's end date is not updated" do
|
230
|
+
expect{ end_date_propagator.call }.to change{
|
231
|
+
base_instance.errors[:base]
|
232
|
+
}.from([])
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'and the child is the child of a child' do
|
236
|
+
before do
|
237
|
+
end
|
238
|
+
|
239
|
+
it "the parent's end date is not updated" do
|
240
|
+
expect{ end_date_propagator.call }.not_to change{
|
241
|
+
base_instance.reload.end_date
|
242
|
+
}
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'base_instance.end_date !nil -> nil' do
|
249
|
+
let(:initial_end_date) { Date.current }
|
250
|
+
let(:end_date) { nil }
|
251
|
+
let(:child_end_date) { initial_end_date }
|
252
|
+
|
253
|
+
it 'does not propagate to the child_instance' do
|
254
|
+
expect{ end_date_propagator.call }.not_to change{
|
255
|
+
child_instance.reload.emancipation_date }
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context 'base_instance.end_date not changed' do
|
260
|
+
let(:end_date) { initial_end_date }
|
261
|
+
|
262
|
+
it 'does not propagate to the child_instance' do
|
263
|
+
expect{ end_date_propagator.call }.not_to change{
|
264
|
+
child_instance.reload.emancipation_date }
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
context 'has access to all children via has_many associations' do
|
269
|
+
let(:end_date) { Date.current }
|
270
|
+
|
271
|
+
it 'changes the end_date of all child associations' do
|
272
|
+
expect{ end_date_propagator.call }.to change{
|
273
|
+
child_instance.reload.emancipation_date }.
|
274
|
+
from(child_instance.emancipation_date).to(base_instance.end_date)
|
275
|
+
.and change{ dog_instance.reload.end_date }
|
276
|
+
.from(dog_instance.end_date).to(base_instance.end_date)
|
277
|
+
.and change{ bird_instance.reload.end_date }
|
278
|
+
.from(bird_instance.end_date).to(base_instance.end_date)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'when child record does not have end_date to update' do
|
284
|
+
let!(:cat_owner_instance) do
|
285
|
+
CatOwner.create(end_date: initial_end_date)
|
286
|
+
end
|
287
|
+
let!(:cat_instance) do
|
288
|
+
Cat.create(cat_owner: cat_owner_instance)
|
289
|
+
end
|
290
|
+
let(:cat_end_date) { nil }
|
291
|
+
let(:end_date) { Date.current }
|
292
|
+
|
293
|
+
before do
|
294
|
+
cat_owner_instance.end_date = end_date
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'does not throw an error' do
|
298
|
+
expect(cat_instance).not_to respond_to(:end_date)
|
299
|
+
expect{ end_date_propagator.call }.not_to raise_error
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'when a class is skipped' do
|
304
|
+
let(:end_date) { Date.current }
|
305
|
+
let(:skipped_classes) { [Tale] }
|
306
|
+
|
307
|
+
before do
|
308
|
+
base_instance
|
309
|
+
tale_instance.save!
|
310
|
+
base_instance.end_date = end_date
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'does not propagate to that class' do
|
314
|
+
expect{ end_date_propagator.call }.not_to change{
|
315
|
+
tale_instance.reload.end_date }
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|