Allow repeated fields in Ruby to accept multiple arguments on push (#5736)

* let repeated fields push arrays

* add varargs push

* better test
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index 8f4c421..29e829e 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -223,6 +223,12 @@
   return _self;
 }
 
+VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) {
+  for (int i = 0; i < RARRAY_LEN(args); i++) {
+    RepeatedField_push(_self, rb_ary_entry(args, i));
+  }
+  return _self;
+}
 
 // Used by parsing handlers.
 void RepeatedField_push_native(VALUE _self, void* data) {
@@ -635,7 +641,7 @@
   rb_define_method(klass, "[]", RepeatedField_index, -1);
   rb_define_method(klass, "at", RepeatedField_index, -1);
   rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
-  rb_define_method(klass, "push", RepeatedField_push, 1);
+  rb_define_method(klass, "push", RepeatedField_push_vararg, -2);
   rb_define_method(klass, "<<", RepeatedField_push, 1);
   rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
   rb_define_method(klass, "replace", RepeatedField_replace, 1);
diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb
index a9c44f5..3876300 100644
--- a/ruby/tests/common_tests.rb
+++ b/ruby/tests/common_tests.rb
@@ -708,6 +708,27 @@
     assert proto_module::TestEnum::resolve(:C) == 3
   end
 
+  def test_repeated_push
+    m = proto_module::TestMessage.new
+
+    m.repeated_string += ['one']
+    m.repeated_string += %w[two three]
+    assert_equal %w[one two three], m.repeated_string
+
+    m.repeated_string.push *['four', 'five']
+    assert_equal %w[one two three four five], m.repeated_string
+
+    m.repeated_string.push 'six', 'seven'
+    assert_equal %w[one two three four five six seven], m.repeated_string
+
+    m = proto_module::TestMessage.new
+
+    m.repeated_msg += [proto_module::TestMessage2.new(:foo => 1), proto_module::TestMessage2.new(:foo => 2)]
+    m.repeated_msg += [proto_module::TestMessage2.new(:foo => 3)]
+    m.repeated_msg.push proto_module::TestMessage2.new(:foo => 4), proto_module::TestMessage2.new(:foo => 5)
+    assert_equal [1, 2, 3, 4, 5], m.repeated_msg.map {|x| x.foo}
+  end
+
   def test_parse_serialize
     m = proto_module::TestMessage.new(:optional_int32 => 42,
                                       :optional_string => "hello world",
diff --git a/ruby/tests/repeated_field_test.rb b/ruby/tests/repeated_field_test.rb
index df8ede4..ced9de8 100644
--- a/ruby/tests/repeated_field_test.rb
+++ b/ruby/tests/repeated_field_test.rb
@@ -221,7 +221,7 @@
 
   def test_push
     m = TestMessage.new
-    reference_arr = %w(foo bar baz)
+    reference_arr = %w[foo bar baz]
     m.repeated_string += reference_arr.clone
 
     check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
@@ -230,10 +230,9 @@
     check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
       arr << 'fizz'
     end
-    #TODO: push should support multiple
-    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
-    #   arr.push('fizz', 'buzz')
-    # end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.push('fizz', 'buzz')
+    end
   end
 
   def test_clear