Skip to content

Commit f736e2b

Browse files
authored
Merge pull request #390 from ruby-protobuf/ah/fix_enum_hash_equality
Fix enum hash equality
2 parents 7962468 + da5b844 commit f736e2b

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

lib/protobuf/enum.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,25 @@ def class
285285
tag.class
286286
end
287287

288+
# Protobuf::Enum delegates methods to Fixnum, which has a custom hash equality method (`eql?`)
289+
# This causes enum values to be equivalent when using `==`, `===`, `equals?`, but not `eql?`**:
290+
#
291+
# 2.3.7 :002 > ::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO)
292+
# => false
293+
#
294+
# However, they are equilvalent to their tag value:
295+
#
296+
# 2.3.7 :002 > ::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO.tag)
297+
# => true
298+
#
299+
# **The implementation changed in Ruby 2.5, so this only affects Ruby versions less than v2.4.
300+
#
301+
# Use the hash equality implementation from Object#eql?, which is equivalent to == instead.
302+
#
303+
def eql?(other)
304+
self == other
305+
end
306+
288307
def inspect
289308
"\#<Protobuf::Enum(#{parent_class})::#{name}=#{tag}>"
290309
end

spec/lib/protobuf/enum_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,20 @@
282282
specify { subject.try { |yielded| expect(yielded).to eq(subject) } }
283283
end
284284

285+
describe '#eql?' do
286+
it "is equal to itself" do
287+
expect(::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO)).to be(true)
288+
end
289+
290+
it "is equal to it's tag" do
291+
expect(::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO.tag)).to be(true)
292+
end
293+
294+
it "is not equal to it's name" do
295+
expect(::Test::EnumTestType::ZERO.eql?(::Test::EnumTestType::ZERO.name)).to be(false)
296+
end
297+
end
298+
285299
context 'when coercing from enum' do
286300
subject { Test::StatusType::PENDING }
287301
it { is_expected.to eq(0) }

0 commit comments

Comments
 (0)