I have created an object that failed to marshal due to a "singleton metaclass definition executed on runtime" (Is this description of what the code does correct?).
This is performed by following code:
# define class X that my use singleton class metaprogramming features
# through call of method :break_marshalling!
class X
def break_marshalling!
meta_class = class << self
self
end
meta_class.send(:define_method, :method_y) do
return
end
end
end
# prepare my instance of X now
instance_of_x = X.new
# marshalling fine here
Marshal.dump instance_of_x
# break marshalling with metprogramming features
instance_of_x.break_marshalling!
Marshal.dump instance_of_x
# fails with TypeError: singleton can't be dumped
What can I do to make the object marshall correct? Is it possible to "remove" the singleton components from class X
of object instance_of_x
?
I really need an advise on that because of some of our objects needed to be cached through Marshal.dump serialization mechanism. This code is executed in ruby-1.9.3 but I expect it to behave similar in ruby-2.0 or ruby-2.1
The one-liner way to (usually) remove singleton information from instance_of_x
:
instance_of_x = instance_of_x.dup
You can define custom marshal_dump
and marshal_load
methods:
class X
def break_marshalling!
meta_class = class << self
self
end
meta_class.send(:define_method, :method_y) do
return
end
end
# This should return an array of instance variables
# needed to correctly restore any X instance. Assuming none is needed
def marshal_dump
[]
end
# This should define instance variables
# needed to correctly restore any X instance. Assuming none is needed
def marshal_load(_)
[]
end
end
# Works fine
restored_instance_of_x =
Marshal.load Marshal.dump(X.new.tap { |x| x.break_marshalling! })
# Does not work
restored_instance_of_x.method_y
If you want you can manage dynamic methods definitions via method_missing
:
class X
def method_missing(name, *args)
if name == :method_y
break_marshalling!
public_send name, *args
else
super
end
end
end
# Works fine
Marshal.load(Marshal.dump(X.new)).method_y
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With