christophe (dot) poucet (at) gmail (dot) com wrote:
Concerning tracking references.
I want to store each object as a separate value. I can assure that
each object has a unique id (all the objects that need to be stored
separately are instance_of? Managed), however if I marshal the objects
one by one, then the references they might hold internally to each
other will of course no long work. How would I solve this problem?
Obviously I need to replace the references by some sort value that
refers to it, or otherwise anything that is referred will be stored
multiple times. However I'm not quite sure how to put the hooks in
place for this.
Christophe.
Here's one way:
class Node
@@nodes = Hash.new {|h,k| raise ArgumentError, "Missing node
#{k.inspect}"}
# The id of a node can be anything but +nil+.
attr_reader :id
def initialize id
@id = id
@@nodes[id] = self
end
attr_accessor :prev_node, :next_node
attr_accessor :temp_data
# don't want this to persist (maybe it's a cache, or simply
# undumpable, like a proc, or a file, or a singleton).
def marshal_dump
[prev_node, next_node].map {|node| node && node.id}
end
def marshal_load(dumped_obj)
@prev_node, @next_node = dumped_obj.map do |node_id|
node_id.nil? ? nil : @@nodes[node_id]
end
end
def self.delete id
@@nodes.delete id
end
end
node1 = Node.new "One"
node2 = Node.new 2
node1.next_node = node2
node2.prev_node = node1
node1.temp_data = STDOUT
node2.temp_data = proc {"foo"}
p node1
node1_dumped = Marshal.dump(node1)
p Marshal.load(Marshal.dump(node1))
Node.delete 2
p Marshal.load(node1_dumped)
# This should raise an exception, to show that the referred node is not
# stored in node1_dumped, and not in the @@nodes hash.
__END__
#<Node:0xb7dfe260 @temp_data=#<IO:0xb7e4c078>, @id="One",
@next_node=#<Node:0xb7dfe24c
@temp_data=#<Proc:0xb7dfe9e0@marshal-refs2.rb:40>, @id=2,
@prev_node=#<Node:0xb7dfe260 ...>>>
#<Node:0xb7dfdeb4 @next_node=#<Node:0xb7dfe24c
@temp_data=#<Proc:0xb7dfe9e0@marshal-refs2.rb:40>, @id=2,
@prev_node=#<Node:0xb7dfe260 @temp_data=#<IO:0xb7e4c078>, @id="One",
@next_node=#<Node:0xb7dfe24c ...>>>, @prev_node=nil>
marshal-refs2.rb:2: Missing node 2 (ArgumentError)
from marshal-refs2.rb:2:in `call'
from marshal-refs2.rb:24:in `default'
from marshal-refs2.rb:24:in `'
from marshal-refs2.rb:24:in `marshal_load'
from marshal-refs2.rb:23:in `map'
from marshal-refs2.rb:23:in `marshal_load'
from marshal-refs2.rb:47:in `load'
from marshal-refs2.rb:47
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407