Marshaling an object destroys dynamically created methods

P

Patrick Li

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)
 
M

Mikael H©ªilund

I'm not in a position to test, but it looksnto me like the method =20
print simply isn't created on the unMarshaled object. Since the =20
methods in Kernel are included in Object as private methods, you get =20
the same error message from Object.new.print or Object.new.throw. I'm =20=

not familiar with Marshaling at all, but this may help you debug. Good =20=

luck :)

--=20
Mikael H=A9=AAilund, CTO of Meta.io
 
P

Pit Capitain

2008/8/20 Patrick Li said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top