Skip to content

Commit

Permalink
Merge pull request protocolbuffers#334 from skippy/allow-msg-to-accep…
Browse files Browse the repository at this point in the history
…t-nil

ruby: allow a message field to be unset
  • Loading branch information
cfallin committed May 3, 2015
2 parents dcf1213 + 6467826 commit 16a283f
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 6 deletions.
4 changes: 3 additions & 1 deletion ruby/ext/google/protobuf_c/storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
break;
}
case UPB_TYPE_MESSAGE: {
if (CLASS_OF(value) != type_class) {
if (CLASS_OF(value) == CLASS_OF(Qnil)) {
value = Qnil;
} else if (CLASS_OF(value) != type_class) {
rb_raise(rb_eTypeError,
"Invalid type %s to assign to submessage field.",
rb_class2name(CLASS_OF(value)));
Expand Down
15 changes: 10 additions & 5 deletions ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -659,22 +659,27 @@ protected IRubyObject setField(ThreadContext context, Descriptors.FieldDescripto
} else {
Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
IRubyObject typeClass = context.runtime.getObject();
boolean addValue = true;
if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
if (value.isNil()){
addValue = false;
}
} else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context);
}
Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
// Convert integer enum to symbol
if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
if (Utils.isRubyNum(value)) {
Descriptors.EnumValueDescriptor val =
enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName());
}
}
this.fields.put(fieldDescriptor, value);
if (addValue) {
Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
this.fields.put(fieldDescriptor, value);
} else {
this.fields.remove(fieldDescriptor);
}
}
}
return context.runtime.getNil();
Expand Down
2 changes: 2 additions & 0 deletions ruby/tests/basic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ def test_setters
assert m.optional_bytes == "world"
m.optional_msg = TestMessage2.new(:foo => 42)
assert m.optional_msg == TestMessage2.new(:foo => 42)
m.optional_msg = nil
assert m.optional_msg == nil
end

def test_ctor_args
Expand Down

0 comments on commit 16a283f

Please sign in to comment.