require 'facets/core/kernel/object_class' module Kernel # Create a hash representation of an object. def to_data( deep=false ) #return self if Hash === object_class data = {} data.data_represents( object_class ) instance_variables.each do |iv| name = iv[1..-1].to_sym # remove @ value = instance_variable_get(iv) value = value.to_data if deep data[name] = value end data end # Restore objects state from a hash representation of the object. def from_data(snap) #instance_variables.each { |iv| instance_variable_set(iv, snap[iv]) } snap.each { |iv, value| instance_variable_set("@#{iv}", value) } self end end class Hash def data_represents( klass ) @data_represents = klass end def data_represents?( klass ) @data_represents == klass end def to_object( klass=nil ) #raise unless @data_represention obj = (klass||@data_represents).allocate obj.from_data( self ) end def to_data() dup end def from_data(snap) replace(snap) end end class Array def to_data ; dup ; end end class String def to_data() dup end def from_data(snap) replace(snap) end end class Struct def to_data snap = Hash.new each_pair {|k,v| snap[k] = v} snap end def from_data(snap) snap.each_pair {|k,v| send(k.to_s + "=", v)} end end =begin test class TestToData < Test::Unit::TestCase class X attr_accessor :a, :b, :c def initialize(a, b, c) @a, @b, @c = a, b, c end def ==( other ) return false if @a != other.a return false if @b != other.b return false if @c != other.c true end end def test_001 x = X.new( 1, 2, 3 ) assert_equal( { :a=>1, :b=>2, :c=>3 }, x.to_data ) end def test_002 x = X.new( 1, 2, [:a,:b] ) assert_equal( { :a=>1, :b=>2, :c=>[:a,:b] }, x.to_data ) end def test_003 x = X.new( 1, 2, 3 ) d = x.to_data x.a = 3 assert_equal( 3, x.a ) x.from_data(d) assert_equal( 1, x.a ) end def test_004 x = X.new( 1, 2, 3 ) d = x.to_data y = d.to_object assert_equal( x, y ) end end =end