Marshaling an object destroys dynamically created methods

I noticed this this afternoon:
Unmarshaling a marshaled object, makes all dynamically created methods
private.

#Here’s a class that dynamically creates the method MyPage#print()
class MyPage
def initialize
MyPage.class_eval do
def print
puts @a
end
end
end
end

#Test the class
page = MyPage.new
page.print #prints nil

#Marshal the object
File.open(“object.obj”,“w”) do |f|
Marshal.dump(page, f)
end

#UnMarshal the object, and try printing again
page = nil
File.open(“object.obj”,“r”) do |f|
page = Marshal.load(f)
end
page.print

#gives me:
#private method `print’ called for #<MyPage:0x27af394 @a=3>
(NoMethodError)

From: Patrick Li [mailto:[email protected]]

I noticed this this afternoon:

Unmarshaling a marshaled object, makes all dynamically created methods

private.

check your ruby version, pls

class MyPage
def initialize
MyPage.class_eval do
def print
puts @a
end
end
end
end
#=> nil

#Test the class
page = MyPage.new
#=> #MyPage:0x28d7154
page.print #prints nil
nil
#=> nil

#Marshal the object
File.open(“object.obj”,“w”) do |f|
Marshal.dump(page, f)
end
#=> #<File:object.obj (closed)>

#UnMarshal the object, and try printing again
page = nil
#=> nil
File.open(“object.obj”,“r”) do |f|
page = Marshal.load(f)
end
#=> #MyPage:0x28c1980
page.print
nil
#=> nil

[RUBY_VERSION,RUBY_PATCHLEVEL,RUBY_RELEASE_DATE,RUBY_PLATFORM]
#=> [“1.8.6”, 286, “2008-08-08”, “i386-mswin32”]

kind regards -botp

I’m not in a position to test, but it looksnto me like the method
print simply isn’t created on the unMarshaled object. Since the
methods in Kernel are included in Object as private methods, you get
the same error message from Object.new.print or Object.new.throw. I’m
not familiar with Marshaling at all, but this may help you debug. Good
luck :slight_smile:


Mikael H©ªilund, CTO of Meta.io

On Aug 20, 2008, at 6:17 AM, Patrick Li [email protected]

2008/8/20 Patrick Li [email protected]:

I noticed this this afternoon:
Unmarshaling a marshaled object, makes all dynamically created methods
private.

Patrick, that’s not correct. Classes and methods aren’t changed upon
marshalling.

#Here’s a class that dynamically creates the method MyPage#print()
class MyPage
def initialize
MyPage.class_eval do
def print
puts @a
end
end
end
end

This creates a MyPage#print method for all MyPage instances as soon
as the first instance is created.

#Test the class
page = MyPage.new

Here the MyPage#print method is created.

page.print #prints nil

As expected.

#Marshal the object
File.open(“object.obj”,“w”) do |f|
Marshal.dump(page, f)
end

Maybe you should stop Ruby at this point, see below. If you just
continue with the following code, you don’t get the output you’ve
shown, as botp already wrote.

#UnMarshal the object, and try printing again
page = nil
File.open(“object.obj”,“r”) do |f|
page = Marshal.load(f)
end
page.print

#gives me:
#private method `print’ called for #<MyPage:0x27af394 @a=3>
(NoMethodError)

No, you don’t get this error. See botp’s example.

If you stop Ruby at the point shown above, then start a new session,
define the MyPage class as above, and then run the unmarshalling code,
then it’s normal and expected that you get a NoMethodError.
Unmarshaling an object doesn’t call it’s class’ #initialize method, so
the new method MyPage#print never is defined in the second Ruby
session. That’s why you are calling the private method Kernel#print
and get the error.

Regards,
Pit