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)

···

--
Posted via http://www.ruby-forum.com/.

# 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

···

From: Patrick Li [mailto:patrickli_2001@hotmail.com]

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 <patrickli_2001@hotmail.com> wrote:

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)
--
Posted via http://www.ruby-forum.com/\.

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

···

2008/8/20 Patrick Li <patrickli_2001@hotmail.com>: