This is an automated email from the ASF dual-hosted git repository.

shiro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 84e10b6  ARROW-4174: [Ruby] Add support for building composite array 
from raw Ruby objects
84e10b6 is described below

commit 84e10b69a8043f507eabc7b3f224a265baa33a1a
Author: Kouhei Sutou <[email protected]>
AuthorDate: Mon Jan 7 19:58:39 2019 +0900

    ARROW-4174: [Ruby] Add support for building composite array from raw Ruby 
objects
    
    Author: Kouhei Sutou <[email protected]>
    
    Closes #3327 from kou/ruby-array-builder and squashes the following commits:
    
    20e5874c <Kouhei Sutou> Add support for old GObject Introspection
    36b993ba <Kouhei Sutou>  Add support for building composite array from raw 
Ruby objects
---
 c_glib/arrow-glib/array-builder.cpp                |  21 +++
 c_glib/arrow-glib/array-builder.h                  |   3 +
 c_glib/arrow-glib/decimal128.cpp                   |  18 +++
 c_glib/arrow-glib/decimal128.h                     |   4 +
 ruby/red-arrow/lib/arrow/array.rb                  |   8 +-
 .../{array.rb => decimal128-array-builder.rb}      |  71 +++++-----
 ruby/red-arrow/lib/arrow/field.rb                  |   2 +-
 ruby/red-arrow/lib/arrow/list-array-builder.rb     |  86 ++++++++++++
 ruby/red-arrow/lib/arrow/loader.rb                 |   5 +-
 ruby/red-arrow/lib/arrow/struct-array-builder.rb   | 129 ++++++++++++++++++
 .../test/test-decimal128-array-builder.rb          |  95 ++++++++++++++
 ...st-struct-array.rb => test-decimal128-array.rb} |  36 ++---
 ruby/red-arrow/test/test-list-array-builder.rb     |  62 +++++++++
 .../{test-struct-array.rb => test-list-array.rb}   |  30 ++---
 ruby/red-arrow/test/test-struct-array-builder.rb   | 145 +++++++++++++++++++++
 ruby/red-arrow/test/test-struct-array.rb           |  21 +++
 16 files changed, 661 insertions(+), 75 deletions(-)

diff --git a/c_glib/arrow-glib/array-builder.cpp 
b/c_glib/arrow-glib/array-builder.cpp
index 5f2d411..095c68d 100644
--- a/c_glib/arrow-glib/array-builder.cpp
+++ b/c_glib/arrow-glib/array-builder.cpp
@@ -3863,6 +3863,27 @@ 
garrow_decimal128_array_builder_append_value(GArrowDecimal128ArrayBuilder *build
      "[decimal128-array-builder][append-value]");
 }
 
+/**
+ * garrow_decimal128_array_builder_append_null:
+ * @builder: A #GArrowDecimal128ArrayBuilder.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: %TRUE on success, %FALSE if there was an error.
+ *
+ * It appends a new NULL element.
+ *
+ * Since: 0.12.0
+ */
+gboolean
+garrow_decimal128_array_builder_append_null(GArrowDecimal128ArrayBuilder 
*builder,
+                                            GError **error)
+{
+  return garrow_array_builder_append_null<arrow::Decimal128Builder *>
+    (GARROW_ARRAY_BUILDER(builder),
+     error,
+     "[decimal128-array-builder][append-null]");
+}
+
 G_END_DECLS
 
 GArrowArrayBuilder *
diff --git a/c_glib/arrow-glib/array-builder.h 
b/c_glib/arrow-glib/array-builder.h
index b2ad6f4..bc0a994 100644
--- a/c_glib/arrow-glib/array-builder.h
+++ b/c_glib/arrow-glib/array-builder.h
@@ -1486,5 +1486,8 @@ GARROW_AVAILABLE_IN_0_12
 gboolean 
garrow_decimal128_array_builder_append_value(GArrowDecimal128ArrayBuilder 
*builder,
                                                       GArrowDecimal128 *value,
                                                       GError **error);
+GARROW_AVAILABLE_IN_0_12
+gboolean 
garrow_decimal128_array_builder_append_null(GArrowDecimal128ArrayBuilder 
*builder,
+                                                     GError **error);
 
 G_END_DECLS
diff --git a/c_glib/arrow-glib/decimal128.cpp b/c_glib/arrow-glib/decimal128.cpp
index e30eb7e..d87a501 100644
--- a/c_glib/arrow-glib/decimal128.cpp
+++ b/c_glib/arrow-glib/decimal128.cpp
@@ -137,6 +137,24 @@ garrow_decimal128_new_integer(const gint64 data)
 }
 
 /**
+ * garrow_decimal128_equal:
+ * @decimal: A #GArrowDecimal128.
+ * @other_decimal: A #GArrowDecimal128 to be compared.
+ *
+ * Returns: %TRUE if both of them is the same value, %FALSE otherwise.
+ *
+ * Since: 0.12.0
+ */
+gboolean
+garrow_decimal128_equal(GArrowDecimal128 *decimal,
+                        GArrowDecimal128 *other_decimal)
+{
+  const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
+  const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
+  return *arrow_decimal == *arrow_other_decimal;
+}
+
+/**
  * garrow_decimal128_to_string_scale:
  * @decimal: A #GArrowDecimal128.
  * @scale: The scale of the decimal.
diff --git a/c_glib/arrow-glib/decimal128.h b/c_glib/arrow-glib/decimal128.h
index 918cf3d..e8fa599 100644
--- a/c_glib/arrow-glib/decimal128.h
+++ b/c_glib/arrow-glib/decimal128.h
@@ -20,6 +20,7 @@
 #pragma once
 
 #include <arrow-glib/gobject-type.h>
+#include <arrow-glib/version.h>
 
 G_BEGIN_DECLS
 
@@ -37,6 +38,9 @@ struct _GArrowDecimal128Class
 
 GArrowDecimal128 *garrow_decimal128_new_string(const gchar *data);
 GArrowDecimal128 *garrow_decimal128_new_integer(const gint64 data);
+GARROW_AVAILABLE_IN_0_12
+gboolean garrow_decimal128_equal(GArrowDecimal128 *decimal,
+                                 GArrowDecimal128 *other_decimal);
 gchar *garrow_decimal128_to_string_scale(GArrowDecimal128 *decimal,
                                          gint32 scale);
 gchar *garrow_decimal128_to_string(GArrowDecimal128 *decimal);
diff --git a/ruby/red-arrow/lib/arrow/array.rb 
b/ruby/red-arrow/lib/arrow/array.rb
index 0492241..359e70e 100644
--- a/ruby/red-arrow/lib/arrow/array.rb
+++ b/ruby/red-arrow/lib/arrow/array.rb
@@ -21,12 +21,14 @@ module Arrow
 
     class << self
       def new(*args)
-        return super if args.size != 1
-
         builder_class_name = "#{name}Builder"
         if const_defined?(builder_class_name)
           builder_class = const_get(builder_class_name)
-          builder_class.build(*args)
+          if args.size == builder_class.method(:build).arity
+            builder_class.build(*args)
+          else
+            super
+          end
         else
           super
         end
diff --git a/ruby/red-arrow/lib/arrow/array.rb 
b/ruby/red-arrow/lib/arrow/decimal128-array-builder.rb
similarity index 50%
copy from ruby/red-arrow/lib/arrow/array.rb
copy to ruby/red-arrow/lib/arrow/decimal128-array-builder.rb
index 0492241..9a849d4 100644
--- a/ruby/red-arrow/lib/arrow/array.rb
+++ b/ruby/red-arrow/lib/arrow/decimal128-array-builder.rb
@@ -15,51 +15,50 @@
 # specific language governing permissions and limitations
 # under the License.
 
-module Arrow
-  class Array
-    include Enumerable
+require "bigdecimal"
 
+module Arrow
+  class Decimal128ArrayBuilder
     class << self
-      def new(*args)
-        return super if args.size != 1
-
-        builder_class_name = "#{name}Builder"
-        if const_defined?(builder_class_name)
-          builder_class = const_get(builder_class_name)
-          builder_class.build(*args)
-        else
-          super
-        end
+      def build(data_type, values)
+        builder = new(data_type)
+        builder.build(values)
       end
     end
 
-    def [](i)
-      i += length if i < 0
-      if null?(i)
-        nil
-      else
-        get_value(i)
+    alias_method :append_value_raw, :append_value
+    def append_value(value)
+      case value
+      when nil
+        return append_null
+      when String
+        value = Decimal128.new(value)
+      when Float
+        value = Decimal128.new(value.to_s)
+      when BigDecimal
+        value = Decimal128.new(value.to_s)
       end
+      append_value_raw(value)
     end
 
-    def each
-      return to_enum(__method__) unless block_given?
-
-      length.times do |i|
-        yield(self[i])
-      end
-    end
-
-    def reverse_each
-      return to_enum(__method__) unless block_given?
-
-      (length - 1).downto(0) do |i|
-        yield(self[i])
+    def append_values(values, is_valids=nil)
+      if is_valids
+        is_valids.each_with_index do |is_valid, i|
+          if is_valid
+            append_value(values[i])
+          else
+            append_null
+          end
+        end
+      else
+        values.each do |value|
+          if value.nil?
+            append_null
+          else
+            append_value(value)
+          end
+        end
       end
     end
-
-    def to_arrow
-      self
-    end
   end
 end
diff --git a/ruby/red-arrow/lib/arrow/field.rb 
b/ruby/red-arrow/lib/arrow/field.rb
index 8c7c8ea..599ff30 100644
--- a/ruby/red-arrow/lib/arrow/field.rb
+++ b/ruby/red-arrow/lib/arrow/field.rb
@@ -108,7 +108,7 @@ module Arrow
         name = args[0]
         data_type = DataType.resolve(args[1])
       else
-        message = "wrong number of arguments (given, #{n_args}, expected 1..2)"
+        message = "wrong number of arguments (given #{n_args}, expected 1..2)"
         raise ArgumentError, message
       end
 
diff --git a/ruby/red-arrow/lib/arrow/list-array-builder.rb 
b/ruby/red-arrow/lib/arrow/list-array-builder.rb
new file mode 100644
index 0000000..aa093c2
--- /dev/null
+++ b/ruby/red-arrow/lib/arrow/list-array-builder.rb
@@ -0,0 +1,86 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Arrow
+  class ListArrayBuilder
+    class << self
+      def build(data_type, values)
+        builder = new(data_type)
+        builder.build(values)
+      end
+    end
+
+    alias_method :append_value_raw, :append_value
+
+    # @overload append_value
+    #
+    #   Starts appending a list record. You also need to append list
+    #   value by {#value_builder}.
+    #
+    # @overload append_value(list)
+    #
+    #   Appends a list record including list value.
+    #
+    #   @param value [nil, ::Array] The list value of the record.
+    #
+    #     If this is `nil`, the list record is null.
+    #
+    #     If this is `Array`, it's the list value of the record.
+    #
+    # @since 0.12.0
+    def append_value(*args)
+      n_args = args.size
+
+      case n_args
+      when 0
+        append_value_raw
+      when 1
+        value = args[0]
+        case value
+        when nil
+          append_null
+        when ::Array
+          append_value_raw
+          @value_builder ||= value_builder
+          @value_builder.append_values(value, nil)
+        else
+          message = "list value must be nil or Array: #{value.inspect}"
+          raise ArgumentError, message
+        end
+      else
+        message = "wrong number of arguments (given #{n_args}, expected 0..1)"
+        raise ArgumentError, message
+      end
+    end
+
+    def append_values(lists, is_valids=nil)
+      if is_valids
+        is_valids.each_with_index do |is_valid, i|
+          if is_valid
+            append_value(lists[i])
+          else
+            append_null
+          end
+        end
+      else
+        lists.each do |list|
+          append_value(list)
+        end
+      end
+    end
+  end
+end
diff --git a/ruby/red-arrow/lib/arrow/loader.rb 
b/ruby/red-arrow/lib/arrow/loader.rb
index 8747476..acd2573 100644
--- a/ruby/red-arrow/lib/arrow/loader.rb
+++ b/ruby/red-arrow/lib/arrow/loader.rb
@@ -43,11 +43,13 @@ module Arrow
       require "arrow/date32-array-builder"
       require "arrow/date64-array"
       require "arrow/date64-array-builder"
+      require "arrow/decimal128-array-builder"
       require "arrow/decimal128-data-type"
       require "arrow/dense-union-data-type"
       require "arrow/dictionary-data-type"
       require "arrow/field"
       require "arrow/file-output-stream"
+      require "arrow/list-array-builder"
       require "arrow/list-data-type"
       require "arrow/path-extension"
       require "arrow/record"
@@ -59,6 +61,7 @@ module Arrow
       require "arrow/slicer"
       require "arrow/sparse-union-data-type"
       require "arrow/struct-array"
+      require "arrow/struct-array-builder"
       require "arrow/struct-data-type"
       require "arrow/table"
       require "arrow/table-formatter"
@@ -101,7 +104,7 @@ module Arrow
         end
         super(info, klass, method_name)
       else
-       super
+        super
       end
     end
   end
diff --git a/ruby/red-arrow/lib/arrow/struct-array-builder.rb 
b/ruby/red-arrow/lib/arrow/struct-array-builder.rb
new file mode 100644
index 0000000..883ce84
--- /dev/null
+++ b/ruby/red-arrow/lib/arrow/struct-array-builder.rb
@@ -0,0 +1,129 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Arrow
+  class StructArrayBuilder
+    class << self
+      def build(data_type, values)
+        builder = new(data_type)
+        builder.build(values)
+      end
+    end
+
+    def [](index_or_name)
+      find_field_builder(index_or_name)
+    end
+
+    def find_field_builder(index_or_name)
+      case index_or_name
+      when String, Symbol
+        name = index_or_name
+        (@name_to_builder ||= build_name_to_builder)[name.to_s]
+      else
+        index = index_or_name
+        cached_field_builders[index]
+      end
+    end
+
+    alias_method :append_value_raw, :append_value
+
+    # @overload append_value
+    #
+    #   Starts appending a struct record. You need to append values of
+    #   fields.
+    #
+    # @overload append_value(value)
+    #
+    #   Appends a struct record including values of fields.
+    #
+    #   @param value [nil, ::Array, Hash] The struct record value.
+    #
+    #     If this is `nil`, the struct record is null.
+    #
+    #     If this is `Array` or `Hash`, they are values of fields.
+    #
+    # @since 0.12.0
+    def append_value(*args)
+      n_args = args.size
+
+      case n_args
+      when 0
+        append_value_raw
+      when 1
+        value = args[0]
+        case value
+        when nil
+          append_null
+        when ::Array
+          append_value_raw
+          value.each_with_index do |sub_value, i|
+            self[i].append_value(sub_value)
+          end
+        when Hash
+          append_value_raw
+          value.each do |name, sub_value|
+            self[name].append_value(sub_value)
+          end
+        else
+          message = "struct value must be nil, Array or Hash: #{value.inspect}"
+          raise ArgumentError, message
+        end
+      else
+        message = "wrong number of arguments (given #{n_args}, expected 0..1)"
+        raise ArgumentError, message
+      end
+    end
+
+    def append_values(values, is_valids=nil)
+      if is_valids
+        is_valids.each_with_index do |is_valid, i|
+          if is_valid
+            append_value(values[i])
+          else
+            append_null
+          end
+        end
+      else
+        values.each do |value|
+          append_value(value)
+        end
+      end
+    end
+
+    alias_method :append_null_raw, :append_null
+    def append_null
+      append_null_raw
+      cached_field_builders.each do |builder|
+        builder.append_null
+      end
+    end
+
+    private
+    def cached_field_builders
+      @field_builders ||= field_builders
+    end
+
+    def build_name_to_builder
+      name_to_builder = {}
+      builders = cached_field_builders
+      value_data_type.fields.each_with_index do |field, i|
+        name_to_builder[field.name] = builders[i]
+      end
+      name_to_builder
+    end
+  end
+end
diff --git a/ruby/red-arrow/test/test-decimal128-array-builder.rb 
b/ruby/red-arrow/test/test-decimal128-array-builder.rb
new file mode 100644
index 0000000..8418464
--- /dev/null
+++ b/ruby/red-arrow/test/test-decimal128-array-builder.rb
@@ -0,0 +1,95 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+class Decimal128ArrayBuilderTest < Test::Unit::TestCase
+  def setup
+    @data_type = Arrow::Decimal128DataType.new(8, 2)
+    @builder = Arrow::Decimal128ArrayBuilder.new(@data_type)
+  end
+
+  sub_test_case("#append_value") do
+    test("nil") do
+      @builder.append_value(nil)
+      array = @builder.finish
+      assert_equal(nil, array[0])
+    end
+
+    test("Arrow::Decimal128") do
+      @builder.append_value(Arrow::Decimal128.new("10.1"))
+      array = @builder.finish
+      assert_equal(Arrow::Decimal128.new("10.1"),
+                   array[0])
+    end
+
+    test("String") do
+      @builder.append_value("10.1")
+      array = @builder.finish
+      assert_equal(Arrow::Decimal128.new("10.1"),
+                   array[0])
+    end
+
+    test("Float") do
+      @builder.append_value(10.1)
+      array = @builder.finish
+      assert_equal(Arrow::Decimal128.new("10.1"),
+                   array[0])
+    end
+
+    test("BigDecimal") do
+      @builder.append_value(BigDecimal("10.1"))
+      array = @builder.finish
+      assert_equal(Arrow::Decimal128.new("10.1"),
+                   array[0])
+    end
+  end
+
+  sub_test_case("#append_values") do
+    test("mixed") do
+      @builder.append_values([
+                               Arrow::Decimal128.new("10.1"),
+                               nil,
+                               "10.1",
+                               10.1,
+                               BigDecimal("10.1"),
+                             ])
+      array = @builder.finish
+      assert_equal([
+                     Arrow::Decimal128.new("10.1"),
+                     nil,
+                     Arrow::Decimal128.new("10.1"),
+                     Arrow::Decimal128.new("10.1"),
+                     Arrow::Decimal128.new("10.1"),
+                   ],
+                   array.to_a)
+    end
+
+    test("is_valids") do
+      @builder.append_values([
+                               Arrow::Decimal128.new("10.1"),
+                               nil,
+                               Arrow::Decimal128.new("10.1"),
+                             ])
+      array = @builder.finish
+      assert_equal([
+                     Arrow::Decimal128.new("10.1"),
+                     nil,
+                     Arrow::Decimal128.new("10.1"),
+                   ],
+                   array.to_a)
+    end
+  end
+end
diff --git a/ruby/red-arrow/test/test-struct-array.rb 
b/ruby/red-arrow/test/test-decimal128-array.rb
similarity index 57%
copy from ruby/red-arrow/test/test-struct-array.rb
copy to ruby/red-arrow/test/test-decimal128-array.rb
index 1957db4..9162be8 100644
--- a/ruby/red-arrow/test/test-struct-array.rb
+++ b/ruby/red-arrow/test/test-decimal128-array.rb
@@ -15,22 +15,24 @@
 # specific language governing permissions and limitations
 # under the License.
 
-class StructArrayTest < Test::Unit::TestCase
-  test("#[]") do
-    type = Arrow::StructDataType.new([
-      Arrow::Field.new("field1", :boolean),
-      Arrow::Field.new("field2", :uint64),
-    ])
-    builder = Arrow::StructArrayBuilder.new(type)
-    builder.append
-    builder.get_field_builder(0).append(true)
-    builder.get_field_builder(1).append(1)
-    builder.append
-    builder.get_field_builder(0).append(false)
-    builder.get_field_builder(1).append(2)
-    array = builder.finish
-
-    assert_equal([[true, false], [1, 2]],
-                 [array[0].to_a, array[1].to_a])
+class Decimal128ArrayTest < Test::Unit::TestCase
+  sub_test_case(".new") do
+    test("build") do
+      data_type = Arrow::Decimal128DataType.new(8, 2)
+      values = [
+        10.1,
+        nil,
+        "10.1",
+        BigDecimal("10.1"),
+      ]
+      array = Arrow::Decimal128Array.new(data_type, values)
+      assert_equal([
+                     Arrow::Decimal128.new("10.1"),
+                     nil,
+                     Arrow::Decimal128.new("10.1"),
+                     Arrow::Decimal128.new("10.1"),
+                   ],
+                   array.to_a)
+    end
   end
 end
diff --git a/ruby/red-arrow/test/test-list-array-builder.rb 
b/ruby/red-arrow/test/test-list-array-builder.rb
new file mode 100644
index 0000000..e36f2c8
--- /dev/null
+++ b/ruby/red-arrow/test/test-list-array-builder.rb
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+class ListArrayBuilderTest < Test::Unit::TestCase
+  def setup
+    @data_type = Arrow::ListDataType.new(name: "visible", type: :boolean)
+    @builder = Arrow::ListArrayBuilder.new(@data_type)
+  end
+
+  sub_test_case("#append_value") do
+    test("nil") do
+      @builder.append_value(nil)
+      array = @builder.finish
+      assert_equal(nil, array[0])
+    end
+
+    test("Array") do
+      @builder.append_value([true, false, true])
+      array = @builder.finish
+      assert_equal([true, false, true], array[0].to_a)
+    end
+  end
+
+  sub_test_case("#append_values") do
+    test("[nil, Array]") do
+      @builder.append_values([[false], nil, [true, false, true]])
+      array = @builder.finish
+      assert_equal([
+                     [false],
+                     nil,
+                     [true, false, true],
+                   ],
+                   array.collect {|list| list ? list.to_a : nil})
+    end
+
+    test("is_valids") do
+      @builder.append_values([[false], [true, true], [true, false, true]],
+                             [true, false, true])
+      array = @builder.finish
+      assert_equal([
+                     [false],
+                     nil,
+                     [true, false, true],
+                   ],
+                   array.collect {|list| list ? list.to_a : nil})
+    end
+  end
+end
diff --git a/ruby/red-arrow/test/test-struct-array.rb 
b/ruby/red-arrow/test/test-list-array.rb
similarity index 57%
copy from ruby/red-arrow/test/test-struct-array.rb
copy to ruby/red-arrow/test/test-list-array.rb
index 1957db4..c1f7624 100644
--- a/ruby/red-arrow/test/test-struct-array.rb
+++ b/ruby/red-arrow/test/test-list-array.rb
@@ -15,22 +15,18 @@
 # specific language governing permissions and limitations
 # under the License.
 
-class StructArrayTest < Test::Unit::TestCase
-  test("#[]") do
-    type = Arrow::StructDataType.new([
-      Arrow::Field.new("field1", :boolean),
-      Arrow::Field.new("field2", :uint64),
-    ])
-    builder = Arrow::StructArrayBuilder.new(type)
-    builder.append
-    builder.get_field_builder(0).append(true)
-    builder.get_field_builder(1).append(1)
-    builder.append
-    builder.get_field_builder(0).append(false)
-    builder.get_field_builder(1).append(2)
-    array = builder.finish
-
-    assert_equal([[true, false], [1, 2]],
-                 [array[0].to_a, array[1].to_a])
+class ListArrayTest < Test::Unit::TestCase
+  sub_test_case(".new") do
+    test("build") do
+      data_type = Arrow::ListDataType.new(name: "visible", type: :boolean)
+      values = [
+        [true, false],
+        nil,
+        [false, true, false],
+      ]
+      array = Arrow::ListArray.new(data_type, values)
+      assert_equal(values,
+                   array.collect {|value| value ? value.to_a : nil})
+    end
   end
 end
diff --git a/ruby/red-arrow/test/test-struct-array-builder.rb 
b/ruby/red-arrow/test/test-struct-array-builder.rb
new file mode 100644
index 0000000..205564c
--- /dev/null
+++ b/ruby/red-arrow/test/test-struct-array-builder.rb
@@ -0,0 +1,145 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+class StructArrayBuilderTest < Test::Unit::TestCase
+  def setup
+    @data_type = Arrow::StructDataType.new(visible: {type: :boolean},
+                                           count: {type: :uint64})
+    @builder = Arrow::StructArrayBuilder.new(@data_type)
+  end
+
+  sub_test_case("#append_value") do
+    test("nil") do
+      @builder.append_value(nil)
+      array = @builder.finish
+      assert_equal([
+                     [nil],
+                     [nil],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+
+    test("Array") do
+      @builder.append_value([true, 1])
+      array = @builder.finish
+      assert_equal([
+                     [true],
+                     [1],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+
+    test("Hash") do
+      @builder.append_value(count: 1, visible: true)
+      array = @builder.finish
+      assert_equal([
+                     [true],
+                     [1],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+  end
+
+  sub_test_case("#append_values") do
+    test("[nil]") do
+      @builder.append_values([nil])
+      array = @builder.finish
+      assert_equal([
+                     [nil],
+                     [nil],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+
+    test("[Array]") do
+      @builder.append_values([[true, 1]])
+      array = @builder.finish
+      assert_equal([
+                     [true],
+                     [1],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+
+    test("[Hash]") do
+      @builder.append_values([{count: 1, visible: true}])
+      array = @builder.finish
+      assert_equal([
+                     [true],
+                     [1],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+
+    test("[nil, Array, Hash]") do
+      @builder.append_values([
+                               nil,
+                               [true, 1],
+                               {count: 2, visible: false},
+                             ])
+      array = @builder.finish
+      assert_equal([
+                     [nil, true, false],
+                     [nil, 1, 2],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+
+    test("is_valids") do
+      @builder.append_values([
+                               [true, 1],
+                               [false, 2],
+                               [true, 3],
+                             ],
+                             [
+                               true,
+                               false,
+                               true,
+                             ])
+      array = @builder.finish
+      assert_equal([
+                     [true, nil, true],
+                     [1, nil, 3],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+  end
+end
diff --git a/ruby/red-arrow/test/test-struct-array.rb 
b/ruby/red-arrow/test/test-struct-array.rb
index 1957db4..986b0a9 100644
--- a/ruby/red-arrow/test/test-struct-array.rb
+++ b/ruby/red-arrow/test/test-struct-array.rb
@@ -16,6 +16,27 @@
 # under the License.
 
 class StructArrayTest < Test::Unit::TestCase
+  sub_test_case(".new") do
+    test("build") do
+      data_type = Arrow::StructDataType.new(visible: :boolean,
+                                            count: :uint64)
+      values = [
+        [true, 1],
+        nil,
+        [false, 2],
+      ]
+      array = Arrow::StructArray.new(data_type, values)
+      assert_equal([
+                     [true, nil, false],
+                     [1, nil, 2],
+                   ],
+                   [
+                     array[0].to_a,
+                     array[1].to_a,
+                   ])
+    end
+  end
+
   test("#[]") do
     type = Arrow::StructDataType.new([
       Arrow::Field.new("field1", :boolean),

Reply via email to