Marshaling classes

Guys, how are you?
I’m stuck thinking about how can I save the state of a class. I want to
save the class variables of some classes. Do I have to require to
metaprogramming for this? I mean: save those variables in an object,
then dump it marshaling and then re-construct a class from that object
when is loaded. I’ll try to explain the situation in an example:

class Dog
@@quantity = 5
def self.change_quantity=(n)
@@quantity = n
end
def self.show_quantity
@@quantity
end
end

Dog.change_quantity = 99

File.open(‘anyfile.mrs’, ‘w+’) do |f|
Marshal.dump(Dog, f)
end

Dog.change_quantity = 50

Marshal.load(File.open(‘anyfile.mrs’))

Dog.show_quantity
#=> 50

#I want to show 99

So as you can see I’m very confused. This is probably not the way to do
what I want, do you have any advice for me? The objetive is to save the
“state” of a class, save the values of all his class variables. Thanks.
Damián.

On Sep 12, 2012, at 16:13 , Damin M. Gonzlez [email protected]
wrote:

Guys, how are you?
I’m stuck thinking about how can I save the state of a class. I want to
save the class variables of some classes. Do I have to require to
metaprogramming for this? I mean: save those variables in an object,
then dump it marshaling and then re-construct a class from that object
when is loaded. I’ll try to explain the situation in an example:

Two ways I can think of off of the top of my head:

  1. use maglev-ruby -Mpersistent to run your code and you’re done.

class Dog
@@quantity = 5
def self.change_quantity=(n)
@@quantity = n
end
def self.show_quantity
@@quantity
end
end

  1. Rename your methods to reflect good ruby (def self.quantitiy and def
    self.quantity=) and then make them persist your values. Change the
    getter to a lazy accessor that will read in the value from disk (or
    whatever) and change the setter to persist the change back out.

def self.quantity
@@quantity ||= Marshal.load(…) # or whatever
end

Unfortunately Marshal.dump doesn’t dump even instance variables of a
class, just the name of the class.

–8<----
class Dog
@quantity = 5
def self.change_quantity=(n)
@quantity = n
end
def self.show_quantity
@quantity
end
end

Dog.change_quantity = 99

File.open(‘anyfile.mrs’, ‘w+’) do |f|
Marshal.dump(Dog, f)
end

Dog.change_quantity = 50

Dog2 = Marshal.load(File.open(‘anyfile.mrs’))

puts Dog.show_quantity # 50
puts Dog2.show_quantity # 50
puts Dog.object_id == Dog2.object_id # true
–8<----

$ hexdump -C anyfile.mrs
00000000 04 08 63 08 44 6f 67 |…c.Dog|
00000007

So I guess it’s up to you to iterate over instance_variables:

–8<----
class IVDumper
def initialize(klass)
@klass = klass
@ivs = {}
klass.instance_variables.each do |k|
@ivs[k] = klass.instance_variable_get(k)
end
end
def restore
@ivs.each do |k,v|
@klass.instance_variable_set(k,v)
end
@klass
end
end
def IVDumper(k)
IVDumper.new(k)
end

Dog.change_quantity = 99

File.open(‘anyfile.mrs’, ‘w+’) do |f|
Marshal.dump(IVDumper(Dog), f)
end

Dog.change_quantity = 50

Marshal.load(File.open(‘anyfile.mrs’)).restore

puts Dog.show_quantity # 99
–8<----

You can probably make this more transparent, e.g using _dump/_load
methods in IVDumper

Yes! Both advices help me a lot! Finally I’ve got to require to
metaprogramming for this case. Thank you both guys, for your knowledge.
Damián.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs