Skip to content

Commit cef567e

Browse files
authored
Merge pull request rails#51079 from Shopify/duplicable-tests
Update Method#duplicable? to be consistent with Ruby 3.4
2 parents 9b343c2 + ca6995a commit cef567e

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

activesupport/lib/active_support/core_ext/object/duplicable.rb

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,32 @@ def duplicable?
2828
end
2929
end
3030

31-
class Method
32-
# Methods are not duplicable:
33-
#
34-
# method(:puts).duplicable? # => false
35-
# method(:puts).dup # => TypeError: allocator undefined for Method
36-
def duplicable?
37-
false
38-
end
31+
methods_are_duplicable = begin
32+
Object.instance_method(:duplicable?).dup
33+
true
34+
rescue TypeError
35+
false
3936
end
4037

41-
class UnboundMethod
42-
# Unbound methods are not duplicable:
43-
#
44-
# method(:puts).unbind.duplicable? # => false
45-
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46-
def duplicable?
47-
false
38+
unless methods_are_duplicable
39+
class Method
40+
# Methods are not duplicable:
41+
#
42+
# method(:puts).duplicable? # => false
43+
# method(:puts).dup # => TypeError: allocator undefined for Method
44+
def duplicable?
45+
false
46+
end
47+
end
48+
49+
class UnboundMethod
50+
# Unbound methods are not duplicable:
51+
#
52+
# method(:puts).unbind.duplicable? # => false
53+
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
54+
def duplicable?
55+
false
56+
end
4857
end
4958
end
5059

activesupport/test/core_ext/object/duplicable_test.rb

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,26 @@
66
require "active_support/core_ext/numeric/time"
77

88
class DuplicableTest < ActiveSupport::TestCase
9-
RAISE_DUP = [method(:puts), method(:puts).unbind, Class.new.include(Singleton).instance]
10-
ALLOW_DUP = ["1", "symbol_from_string".to_sym, Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal("4.56"), nil, false, true, 1, 2.3, Complex(1), Rational(1)]
9+
OBJECTS = [
10+
method(:puts), method(:puts).unbind, Class.new.include(Singleton).instance,
11+
"1", "symbol_from_string".to_sym, Object.new, /foo/, [], {}, Time.now, Class.new,
12+
Module.new, BigDecimal("4.56"), nil, false, true, 1, 2.3, Complex(1), Rational(1),
13+
]
1114

12-
def test_duplicable
13-
RAISE_DUP.each do |v|
14-
assert_not v.duplicable?, "#{ v.inspect } should not be duplicable"
15-
assert_raises(TypeError, v.class.name) { v.dup }
16-
end
15+
OBJECTS.each do |v|
16+
test "#{v.class}#duplicable? matches #{v.class}#dup behavior" do
17+
duplicable = begin
18+
v.dup
19+
true
20+
rescue TypeError
21+
false
22+
end
1723

18-
ALLOW_DUP.each do |v|
19-
assert_predicate v, :duplicable?, "#{ v.class } should be duplicable"
20-
assert_nothing_raised { v.dup }
24+
if duplicable
25+
assert_predicate v, :duplicable?
26+
else
27+
assert_not_predicate v, :duplicable?
28+
end
2129
end
2230
end
2331
end

0 commit comments

Comments
 (0)