Skip to content

Commit 01c141b

Browse files
committed
Add tests for exotic rescued error capturing
The idiomatic way to capture exceptions is to assign to a local variable rescue => local_variable However, other kinds of LVALUEs also work: rescue => $global_variable rescue => @@class_variable rescue => @instance_variable rescue => Constant rescue => receiver&.setter_method rescue => receiver.setter_method rescue => receiver[:key]
1 parent 81ed39f commit 01c141b

File tree

2 files changed

+116
-5
lines changed

2 files changed

+116
-5
lines changed

language/fixtures/rescue.rb

+100
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,104 @@
11
module RescueSpecs
2+
class ClassVariableCaptor
3+
def capture(msg)
4+
raise msg
5+
rescue => @@captured_error
6+
:caught
7+
end
8+
9+
def captured_error
10+
@@captured_error
11+
end
12+
end
13+
14+
class ConstantCaptor
15+
# Using lambda gets around the dynamic constant assignment warning
16+
CAPTURE = -> msg {
17+
begin
18+
raise msg
19+
rescue => CapturedError
20+
:caught
21+
end
22+
}
23+
24+
def capture(msg)
25+
CAPTURE.call(msg)
26+
end
27+
28+
def captured_error
29+
CapturedError
30+
end
31+
end
32+
33+
class GlobalVariableCaptor
34+
def capture(msg)
35+
raise msg
36+
rescue => $captured_error
37+
:caught
38+
end
39+
40+
def captured_error
41+
$captured_error
42+
end
43+
end
44+
45+
class InstanceVariableCaptor
46+
attr_reader :captured_error
47+
48+
def capture(msg)
49+
raise msg
50+
rescue => @captured_error
51+
:caught
52+
end
53+
end
54+
55+
class LocalVariableCaptor
56+
attr_reader :captured_error
57+
58+
def capture(msg)
59+
raise msg
60+
rescue => captured_error
61+
@captured_error = captured_error
62+
:caught
63+
end
64+
end
65+
66+
class SafeNavigationSetterCaptor
67+
attr_accessor :captured_error
68+
69+
def capture(msg)
70+
raise msg
71+
rescue => self&.captured_error
72+
:caught
73+
end
74+
end
75+
76+
class SetterCaptor
77+
attr_accessor :captured_error
78+
79+
def capture(msg)
80+
raise msg
81+
rescue => self.captured_error
82+
:caught
83+
end
84+
end
85+
86+
class SquareBracketsCaptor
87+
def capture(msg)
88+
raise msg
89+
rescue => self[:error]
90+
:caught
91+
end
92+
93+
def []=(key, value)
94+
(@hash ||= {})[key] = value
95+
end
96+
97+
def captured_error
98+
@hash[:error]
99+
end
100+
end
101+
2102
def self.begin_else(raise_exception)
3103
begin
4104
ScratchPad << :one

language/rescue_spec.rb

+16-5
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,22 @@ class ArbitraryException < StandardError
2323
end.should == :caught
2424
end
2525

26-
it "can capture the raised exception in a local variable" do
27-
begin
28-
raise SpecificExampleException, "some text"
29-
rescue SpecificExampleException => e
30-
e.message.should == "some text"
26+
{
27+
# Standard use case
28+
'can capture the raised exception in a local variable' => RescueSpecs::LocalVariableCaptor,
29+
# Exotic use cases
30+
'can capture the raised exception in a class variable' => RescueSpecs::ClassVariableCaptor,
31+
'can capture the raised exception in a constant' => RescueSpecs::ConstantCaptor,
32+
'can capture the raised exception in a global variable' => RescueSpecs::GlobalVariableCaptor,
33+
'can capture the raised exception in an instance variable' => RescueSpecs::InstanceVariableCaptor,
34+
'can capture the raised exception using a safely navigated setter method' => RescueSpecs::SafeNavigationSetterCaptor,
35+
'can capture the raised exception using a setter method' => RescueSpecs::SetterCaptor,
36+
'can capture the raised exception using a square brackets setter' => RescueSpecs::SquareBracketsCaptor,
37+
}.each do |description, klass|
38+
it description do
39+
captor = klass.new
40+
captor.capture('some text').should == :caught # Ensure rescue body still runs
41+
captor.captured_error.message.should == 'some text'
3142
end
3243
end
3344

0 commit comments

Comments
 (0)