Skip to content

Commit 9743f96

Browse files
authored
Merge pull request #23 from Kaligo/bugfix/duplicate-error-callback
Prevent duplicate invocation of the error callback when guarding an instance method
2 parents c50cbf9 + b8c40ab commit 9743f96

File tree

5 files changed

+57
-12
lines changed

5 files changed

+57
-12
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 0.9.2
4+
5+
### Bug fixes
6+
7+
- Prevent duplicate invocation of the error callback when guarding an instance
8+
method.
9+
310
## 0.9.1
411

512
### Bug fixes

Gemfile.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
PATH
22
remote: .
33
specs:
4-
stimpack (0.9.1)
4+
stimpack (0.9.2)
55
activesupport (>= 6.1)
66

77
GEM
88
remote: https://rubygems.org/
99
specs:
10-
activesupport (7.0.2.2)
10+
activesupport (7.0.3)
1111
concurrent-ruby (~> 1.0, >= 1.0.2)
1212
i18n (>= 1.6, < 2)
1313
minitest (>= 5.1)
1414
tzinfo (~> 2.0)
1515
ast (2.4.2)
16-
concurrent-ruby (1.1.9)
16+
concurrent-ruby (1.1.10)
1717
diff-lcs (1.4.4)
1818
i18n (1.10.0)
1919
concurrent-ruby (~> 1.0)

lib/stimpack/result_monad/guard_clause.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ module GuardCatcher
2929
def call
3030
super
3131
rescue GuardFailed => e
32-
run_callback(:error)
32+
# Avoid running the error callback in the case where it was already
33+
# called by using `#error` in an instance method that is guarded
34+
# against in the `#call` method.
35+
#
36+
run_callback(:error) unless e.result.klass == self.class
3337

3438
e.result
3539
end

lib/stimpack/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module Stimpack
4-
VERSION = "0.9.1"
4+
VERSION = "0.9.2"
55
end

spec/stimpack/result_monad/guard_clause_spec.rb

+41-7
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@
55
RSpec.describe Stimpack::ResultMonad::GuardClause do
66
subject(:service) { klass }
77

8-
let(:instance) { service.new }
8+
let(:instance) { service.new(private_error: private_error) }
9+
let(:private_error) { false }
910

1011
let(:klass) do
1112
Class.new do
1213
include Stimpack::ResultMonad
1314

1415
result :foo
1516

17+
def initialize(private_error: false)
18+
@private_error = private_error
19+
end
20+
21+
attr_reader :private_error
22+
1623
def success_result(**options)
1724
success(**options)
1825
end
@@ -27,9 +34,12 @@ def self.to_s
2734

2835
def call
2936
guard :foo
37+
3038
bar_result = guard { bar }
3139
baz_result = guard { baz }
3240

41+
guard { qux } if private_error
42+
3343
success(foo: bar_result + baz_result)
3444
rescue StandardError
3545
error(errors: "Something went wrong, but not a guard fail.")
@@ -48,13 +58,18 @@ def bar
4858
def baz
4959
pass("Baz")
5060
end
61+
62+
def qux
63+
error(errors: ["Same class error"])
64+
end
5165
end
5266
end
5367

5468
let(:inner_service_error) do
5569
double(
5670
Stimpack::ResultMonad::Result,
5771
failed?: true,
72+
klass: "Foo",
5873
errors: ["Inner error"]
5974
)
6075
end
@@ -63,6 +78,7 @@ def baz
6378
double(
6479
Stimpack::ResultMonad::Result,
6580
failed?: false,
81+
klass: "Foo",
6682
unwrap!: "Foo",
6783
errors: nil
6884
)
@@ -121,15 +137,33 @@ def baz
121137
end
122138

123139
describe ".before_error" do
124-
before do
125-
allow(instance).to receive(:inspect)
126-
allow(instance).to receive(:foo).and_return(inner_service_error)
140+
context "when inner service fails" do
141+
before do
142+
allow(instance).to receive(:inspect)
143+
allow(instance).to receive(:foo).and_return(inner_service_error)
127144

128-
service.before_error { inspect }
145+
service.before_error { inspect }
146+
147+
instance.()
148+
end
129149

130-
instance.()
150+
it { expect(instance).to have_received(:inspect).once }
131151
end
132152

133-
it { expect(instance).to have_received(:inspect).once }
153+
context "when passing an error from an instance method" do
154+
let(:private_error) { true }
155+
156+
before do
157+
allow(instance).to receive(:inspect)
158+
allow(instance).to receive(:foo).and_return(inner_service_success)
159+
allow(instance).to receive(:bar).and_return(inner_service_success)
160+
161+
service.before_error { inspect }
162+
163+
instance.()
164+
end
165+
166+
it { expect(instance).to have_received(:inspect).once }
167+
end
134168
end
135169
end

0 commit comments

Comments
 (0)