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

ruby-changes:36594

From: tenderlove <ko1@a...>
Date: Tue, 2 Dec 2014 06:35:26 +0900 (JST)
Subject: [ruby-changes:36594] tenderlove:r48675 (trunk): * ext/psych/lib/psych/visitors/to_ruby.rb: support objects that are

tenderlove	2014-12-02 06:35:11 +0900 (Tue, 02 Dec 2014)

  New Revision: 48675

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

  Log:
    * ext/psych/lib/psych/visitors/to_ruby.rb: support objects that are
      marshalable, but inherit from basic object.
      Thanks Sean Griffin <sean@t...>
    
    * ext/psych/lib/psych/visitors/yaml_tree.rb: ditto
    
    * test/psych/test_marshalable.rb: test for fix

  Added files:
    trunk/test/psych/test_marshalable.rb
  Modified files:
    trunk/ChangeLog
    trunk/ext/psych/lib/psych/visitors/to_ruby.rb
    trunk/ext/psych/lib/psych/visitors/yaml_tree.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 48674)
+++ ChangeLog	(revision 48675)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Dec  2 06:34:08 2014  Aaron Patterson <aaron@t...>
+
+	* ext/psych/lib/psych/visitors/to_ruby.rb: support objects that are
+	  marshalable, but inherit from basic object.
+	  Thanks Sean Griffin <sean@t...>
+
+	* ext/psych/lib/psych/visitors/yaml_tree.rb: ditto
+
+	* test/psych/test_marshalable.rb: test for fix
+
 Tue Dec  2 06:32:02 2014  Nobuyoshi Nakada  <nobu@r...>
 
 	* parse.y (ripper_flush_string_content): preserve the dispatched
Index: ext/psych/lib/psych/visitors/yaml_tree.rb
===================================================================
--- ext/psych/lib/psych/visitors/yaml_tree.rb	(revision 48674)
+++ ext/psych/lib/psych/visitors/yaml_tree.rb	(revision 48675)
@@ -27,6 +27,8 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/yaml_tree.rb#L27
 
         def key? target
           @obj_to_node.key? target.object_id
+        rescue NoMethodError
+          false
         end
 
         def id_for target
@@ -411,6 +413,18 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/yaml_tree.rb#L413
         end
       end
 
+      def visit_BasicObject o
+        tag = Psych.dump_tags[o.class]
+        tag ||= "!ruby/marshalable:#{o.class.name}"
+
+        map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
+        register(o, map)
+
+        o.marshal_dump.each(&method(:accept))
+
+        @emitter.end_mapping
+      end
+
       private
       # FIXME: Remove the index and count checks in Psych 3.0
       NULL         = "\x00"
Index: ext/psych/lib/psych/visitors/to_ruby.rb
===================================================================
--- ext/psych/lib/psych/visitors/to_ruby.rb	(revision 48674)
+++ ext/psych/lib/psych/visitors/to_ruby.rb	(revision 48675)
@@ -271,6 +271,21 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/to_ruby.rb#L271
           end
           map
 
+        when /^!ruby\/marshalable:(.*)$/
+          name = $1
+          klass = resolve_class(name)
+          obj = register(o, klass.allocate)
+
+          if obj.respond_to?(:init_with)
+            init_with(obj, revive_hash({}, o), o)
+          elsif obj.respond_to?(:marshal_load)
+            marshal_data = o.children.map(&method(:accept))
+            obj.marshal_load(marshal_data)
+            obj
+          else
+            raise ArgumentError, "Cannot deserialize #{name}"
+          end
+
         else
           revive_hash(register(o, {}), o)
         end
Index: test/psych/test_marshalable.rb
===================================================================
--- test/psych/test_marshalable.rb	(revision 0)
+++ test/psych/test_marshalable.rb	(revision 48675)
@@ -0,0 +1,54 @@ https://github.com/ruby/ruby/blob/trunk/test/psych/test_marshalable.rb#L1
+require_relative 'helper'
+require 'delegate'
+
+module Psych
+  class TestMarshalable < TestCase
+    def test_objects_defining_marshal_dump_and_marshal_load_can_be_dumped
+      sd = SimpleDelegator.new(1)
+      loaded = Psych.load(Psych.dump(sd))
+
+      assert_instance_of(SimpleDelegator, loaded)
+      assert_equal(sd, loaded)
+    end
+
+    class PsychCustomMarshalable < BasicObject
+      attr_reader :foo
+
+      def initialize(foo)
+        @foo = foo
+      end
+
+      def marshal_dump
+        [foo]
+      end
+
+      def mashal_load(data)
+        @foo = data[0]
+      end
+
+      def init_with(coder)
+        @foo = coder['foo']
+      end
+
+      def encode_with(coder)
+        coder['foo'] = 2
+      end
+
+      def respond_to?(method)
+        [:marshal_dump, :marshal_load, :init_with, :encode_with].include?(method)
+      end
+
+      def class
+        PsychCustomMarshalable
+      end
+    end
+
+    def test_init_with_takes_priority_over_marshal_methods
+      obj = PsychCustomMarshalable.new(1)
+      loaded = Psych.load(Psych.dump(obj))
+
+      assert(PsychCustomMarshalable === loaded)
+      assert_equal(2, loaded.foo)
+    end
+  end
+end

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

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