Skip to content

Commit

Permalink
Fix ruby has_...? method (#19731)
Browse files Browse the repository at this point in the history
- Fixes #18807

Closes #19731

COPYBARA_INTEGRATE_REVIEW=#19731 from ntkme:fix-ruby-has 8bc2d01
PiperOrigin-RevId: 712734165
  • Loading branch information
ntkme authored and copybara-github committed Jan 7, 2025
1 parent 1ff30f9 commit 4031c19
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 3 deletions.
3 changes: 2 additions & 1 deletion ruby/ext/google/protobuf_c/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
if (!upb_FieldDef_HasPresence(f)) {
rb_raise(rb_eRuntimeError, "Field does not have presence.");
}
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f) ? Qtrue
: Qfalse;
case METHOD_WRAPPER_GETTER: {
Message* self = ruby_to_Message(_self);
if (upb_Message_HasFieldByDef(self->msg, f)) {
Expand Down
6 changes: 4 additions & 2 deletions ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,9 @@ public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) {
fieldDescriptor = descriptor.findFieldByName(methodName);

if (fieldDescriptor != null && fieldDescriptor.hasPresence()) {
return fields.containsKey(fieldDescriptor) ? runtime.getTrue() : runtime.getFalse();
return (fields.containsKey(fieldDescriptor) || builder.hasField(fieldDescriptor))
? runtime.getTrue()
: runtime.getFalse();
}

} else if (methodName.endsWith(AS_VALUE_SUFFIX)) {
Expand Down Expand Up @@ -952,7 +954,7 @@ protected IRubyObject hasField(ThreadContext context, FieldDescriptor fieldDescr
if (!fieldDescriptor.hasPresence()) {
throw context.runtime.newArgumentError("does not track presence");
}
return fields.containsKey(fieldDescriptor)
return (fields.containsKey(fieldDescriptor) || builder.hasField(fieldDescriptor))
? context.runtime.getTrue()
: context.runtime.getFalse();
}
Expand Down
9 changes: 9 additions & 0 deletions ruby/tests/basic_proto2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ def test_has_field

m = TestMessage.new(:optional_int32 => nil)
refute m.has_optional_int32?
refute TestMessage.descriptor.lookup('optional_int32').has?(m)

m = TestMessage.new(:optional_int32 => 0)
assert m.has_optional_int32?
assert TestMessage.descriptor.lookup('optional_int32').has?(m)

m = TestMessage.decode(TestMessage.encode(m))
assert m.has_optional_int32?
assert TestMessage.descriptor.lookup('optional_int32').has?(m)

assert_raises NoMethodError do
m.has_repeated_msg?
Expand Down

0 comments on commit 4031c19

Please sign in to comment.