Selaa lähdekoodia

Merge pull request #3639 from zanker/zanker/fix-embedded-to_h

Fixed to_h with repeated messages to return hashes in Ruby
Joshua Haberman 8 vuotta sitten
vanhempi
commit
eade82c836

+ 7 - 0
ruby/ext/google/protobuf_c/message.c

@@ -419,6 +419,13 @@ VALUE Message_to_h(VALUE _self) {
       msg_value = Map_to_h(msg_value);
     } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
       msg_value = RepeatedField_to_ary(msg_value);
+
+      if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+        for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
+          VALUE elem = rb_ary_entry(msg_value, i);
+          rb_ary_store(msg_value, i, Message_to_h(elem));
+        }
+      }
     } else if (msg_value != Qnil &&
                upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
       msg_value = Message_to_h(msg_value);

+ 13 - 1
ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java

@@ -367,7 +367,19 @@ public class RubyMessage extends RubyObject {
         for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
             IRubyObject value = getField(context, fdef);
             if (!value.isNil()) {
-                if (value.respondsTo("to_h")) {
+                if (fdef.isRepeated() && !fdef.isMapField()) {
+                    if (fdef.getType() != Descriptors.FieldDescriptor.Type.MESSAGE) {
+                        value = Helpers.invoke(context, value, "to_a");
+                    } else {
+                        RubyArray ary = value.convertToArray();
+                        for (int i = 0; i < ary.size(); i++) {
+                            IRubyObject submsg = Helpers.invoke(context, ary.eltInternal(i), "to_h");
+                            ary.eltInternalSet(i, submsg);
+                        }
+
+                        value = ary.to_ary();
+                    }
+                } else if (value.respondsTo("to_h")) {
                     value = Helpers.invoke(context, value, "to_h");
                 } else if (value.respondsTo("to_a")) {
                     value = Helpers.invoke(context, value, "to_a");

+ 2 - 2
ruby/tests/basic.rb

@@ -927,7 +927,7 @@ module BasicTest
     end
 
     def test_to_h
-      m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
+      m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
       expected_result = {
         :optional_bool=>true,
         :optional_bytes=>"",
@@ -947,7 +947,7 @@ module BasicTest
         :repeated_float=>[],
         :repeated_int32=>[],
         :repeated_int64=>[],
-        :repeated_msg=>[],
+        :repeated_msg=>[{:foo => 100}],
         :repeated_string=>["bar1", "bar2"],
         :repeated_uint32=>[],
         :repeated_uint64=>[]