问题
My object contains an instance variable that point to a File object amongst several other attributes. Because of this Marshal
cannot serialize it. How can I write a bespoke dump
method so to exclude only that instance variable?
class Area
attr_accessor :area
attr_reader :several_other_attributes
........
def initialize(name)
@area = name
@several_other_attributes = ....
@log = File.open( 'test.log', 'w')
end
end
回答1:
You can very easily write a marshal_dump
and marshal_load
method that marshals all but a specified number of instance variables. Here's a fairly generic example of something you could do:
class MarshalTest
attr_reader :foo, :bar, :baz, :t
UNMARSHALED_VARIABLES = [:@foo, :@bar]
def initialize(foo = nil, bar = nil, baz = nil, t = nil)
@foo = foo
@bar = bar
@baz = baz
@t = t
end
def marshal_dump
instance_variables.reject{|m| UNMARSHALED_VARIABLES.include? m}.inject({}) do |vars, attr|
vars[attr] = instance_variable_get(attr)
vars
end
end
def marshal_load(vars)
vars.each do |attr, value|
instance_variable_set(attr, value) unless UNMARSHALED_VARIABLES.include?(attr)
end
end
end
Example usage:
1.9.3-p550 :026 > m = MarshalTest.new(1, 2, 3, 4)
=> #<MarshalTest:0x007ff73194cae8 @foo=1, @bar=2, @baz=3, @t=4>
1.9.3-p550 :027 > m.foo
=> 1
1.9.3-p550 :028 > m.bar
=> 2
1.9.3-p550 :029 > m.baz
=> 3
1.9.3-p550 :030 > m.t
=> 4
1.9.3-p550 :031 > s = Marshal.dump(m)
=> "\x04\bU:\x10MarshalTest{\a:\t@bazi\b:\a@ti\t"
1.9.3-p550 :032 > n = Marshal.load(s)
=> #<MarshalTest:0x007ff73112b828 @baz=3, @t=4>
1.9.3-p550 :033 > n.foo
=> nil
1.9.3-p550 :034 > n.bar
=> nil
1.9.3-p550 :035 > n.baz
=> 3
1.9.3-p550 :036 > n.t
=> 4
As you can see, the instance variables foo
and bar
were ignored in the marshaling/unmarshaling.
来源:https://stackoverflow.com/questions/32876672/how-to-exclude-an-instance-variable-from-marshal-dump