From 70544627cb89a61652d688c53984c68013ab985e Mon Sep 17 00:00:00 2001
From: Zachary Anker <zach.anker@gmail.com>
Date: Tue, 26 Jun 2018 20:27:24 -0700
Subject: [PATCH] When initializing a message, skip a field if value is nil
 (#3693)

---
 ruby/ext/google/protobuf_c/message.c                     | 4 ++++
 .../main/java/com/google/protobuf/jruby/RubyMessage.java | 2 ++
 ruby/tests/basic.rb                                      | 9 +++++++++
 3 files changed, 15 insertions(+)

diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index 3394825c9a..721c111275 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -256,6 +256,10 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
              "Unknown field name '%s' in initialization map entry.", name);
   }
 
+  if (TYPE(val) == T_NIL) {
+    return 0;
+  }
+
   if (is_map_field(f)) {
     VALUE map;
 
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
index 07558fbcf0..c3a0d81c14 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -86,6 +86,8 @@ public class RubyMessage extends RubyObject {
                         throw runtime.newTypeError("Expected string or symbols as hash keys in initialization map.");
                     final Descriptors.FieldDescriptor fieldDescriptor = findField(context, key);
 
+                    if (value.isNil()) return;
+
                     if (Utils.isMapEntry(fieldDescriptor)) {
                         if (!(value instanceof RubyHash))
                             throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" +  key.asJavaString() + "'.");
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 38fe709dc5..0a5c5fb55c 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -212,6 +212,15 @@ module BasicTest
       assert_equal ['foo', 'bar'], m.repeated_string
     end
 
+    def test_ctor_nil_args
+      m = TestMessage.new(:optional_enum => nil, :optional_int32 => nil, :optional_string => nil, :optional_msg => nil)
+
+      assert_equal :Default, m.optional_enum
+      assert_equal 0, m.optional_int32
+      assert_equal "", m.optional_string
+      assert_nil m.optional_msg
+    end
+
     def test_embeddedmsg_hash_init
       m = TestEmbeddedMessageParent.new(:child_msg => {sub_child: {optional_int32: 1}},
                                         :number => 2,