[前][次][番号順一覧][スレッド一覧]

ruby-changes:22279

From: tenderlove <ko1@a...>
Date: Wed, 18 Jan 2012 10:44:37 +0900 (JST)
Subject: [ruby-changes:22279] tenderlove:r34328 (trunk): * ext/psych/lib/psych/visitors/to_ruby.rb: Added ability to load array

tenderlove	2012-01-18 10:44:21 +0900 (Wed, 18 Jan 2012)

  New Revision: 34328

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=34328

  Log:
    * ext/psych/lib/psych/visitors/to_ruby.rb: Added ability to load array
      subclasses with ivars.
    * ext/psych/lib/psych/visitors/yaml_tree.rb: Added ability to dump
      array subclasses with ivars.
    * test/psych/test_array.rb: corresponding tests

  Modified files:
    trunk/ChangeLog
    trunk/ext/psych/lib/psych/visitors/to_ruby.rb
    trunk/ext/psych/lib/psych/visitors/yaml_tree.rb
    trunk/test/psych/test_array.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 34327)
+++ ChangeLog	(revision 34328)
@@ -1,3 +1,11 @@
+Wed Jan 18 10:39:47 2012  Aaron Patterson <aaron@t...>
+
+	* ext/psych/lib/psych/visitors/to_ruby.rb: Added ability to load array
+	  subclasses with ivars.
+	* ext/psych/lib/psych/visitors/yaml_tree.rb: Added ability to dump
+	  array subclasses with ivars.
+	* test/psych/test_array.rb: corresponding tests
+
 Tue Jan 17 17:18:41 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in (SPT_TYPE): enable as SPT_REUSEARGV on Darwin.
Index: ext/psych/lib/psych/visitors/yaml_tree.rb
===================================================================
--- ext/psych/lib/psych/visitors/yaml_tree.rb	(revision 34327)
+++ ext/psych/lib/psych/visitors/yaml_tree.rb	(revision 34328)
@@ -301,9 +301,13 @@
       end
 
       def visit_Array o
-        register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
-        o.each { |c| accept c }
-        @emitter.end_sequence
+        if o.class == ::Array
+          register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
+          o.each { |c| accept c }
+          @emitter.end_sequence
+        else
+          visit_array_subclass o
+        end
       end
 
       def visit_NilClass o
@@ -315,6 +319,39 @@
       end
 
       private
+      def visit_array_subclass o
+        tag = "!ruby/array:#{o.class}"
+        if o.instance_variables.empty?
+          node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
+          register o, node
+          o.each { |c| accept c }
+          @emitter.end_sequence
+        else
+          node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
+          register o, node
+
+          # Dump the internal list
+          accept 'internal'
+          @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
+          o.each { |c| accept c }
+          @emitter.end_sequence
+
+          # Dump the ivars
+          accept 'ivars'
+          @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
+          o.instance_variables.each do |ivar|
+            accept ivar
+            accept o.instance_variable_get ivar
+          end
+          @emitter.end_mapping
+
+          @emitter.end_mapping
+        end
+      end
+
+      def dump_list o
+      end
+
       # '%:z' was no defined until 1.9.3
       if RUBY_VERSION < '1.9.3'
         def format_time time
Index: ext/psych/lib/psych/visitors/to_ruby.rb
===================================================================
--- ext/psych/lib/psych/visitors/to_ruby.rb	(revision 34327)
+++ ext/psych/lib/psych/visitors/to_ruby.rb	(revision 34328)
@@ -119,6 +119,11 @@
             map[accept(a.children.first)] = accept a.children.last
           }
           map
+        when /^!(?:seq|ruby\/array):(.*)$/
+          klass = resolve_class($1)
+          list  = register(o, klass.allocate)
+          o.children.each { |c| list.push accept c }
+          list
         else
           list = register(o, [])
           o.children.each { |c| list.push accept c }
@@ -135,6 +140,17 @@
           members = Hash[*o.children.map { |c| accept c }]
           string = members.delete 'str'
           init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
+        when /^!ruby\/array:(.*)$/
+          klass = resolve_class($1)
+          list  = register(o, klass.allocate)
+
+          members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
+          list.replace members['internal']
+
+          members['ivars'].each do |ivar, v|
+            list.instance_variable_set ivar, v
+          end
+          list
         when /^!ruby\/struct:?(.*)?$/
           klass = resolve_class($1)
 
Index: test/psych/test_array.rb
===================================================================
--- test/psych/test_array.rb	(revision 34327)
+++ test/psych/test_array.rb	(revision 34328)
@@ -2,11 +2,39 @@
 
 module Psych
   class TestArray < TestCase
+    class X < Array
+    end
+
+    class Y < Array
+      attr_accessor :val
+    end
+
     def setup
       super
       @list = [{ :a => 'b' }, 'foo']
     end
 
+    def test_subclass
+      yaml = Psych.dump X.new
+      assert_match X.name, yaml
+
+      list = X.new
+      list << 1
+      assert_equal X, list.class
+      assert_equal 1, list.first
+    end
+
+    def test_subclass_with_attributes
+      y = Psych.load Psych.dump Y.new.tap {|y| y.val = 1}
+      assert_equal Y, y.class
+      assert_equal 1, y.val
+    end
+
+    def test_backwards_with_syck
+      x = Psych.load "--- !seq:#{X.name} []\n\n"
+      assert_equal X, x.class
+    end
+
     def test_self_referential
       @list << @list
       assert_cycle(@list)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]