logo search
Программирование на языке Ruby

10.2.2. Более сложный маршалинг

Иногда мы хотим настроить маршалинг под свои нужды. Такую возможность дают методы _load и _dump. Они вызываются во время выполнения маршалинга, чтобы вы могли самостоятельно реализовать преобразование данных в строку и обратно.

В следующем примере человек получает 5-процентный доход на начальный капитал с момента рождения. Мы не храним ни возраст, ни текущий баланс, поскольку они являются функциями времени.

class Person

 attr_reader :name

 attr_reader :age

 attr_reader :balance

 def initialize(name,birthdate,beginning)

  @name = name

  @birthdate = birthdate

  @beginning = beginning

  @age = (Time.now - @birthdate)/(365*86400)

  @balance = @beginning*(1.05**@age)

 end

 def marshal_dump

  Struct.new("Human",:name,:birthdate,:beginning)

  str = Struct::Human.new(@name, @birthdate, @beginning)

  str

 end

 def marshal_load(str)

  self.instance_eval do

   initialize(str.name, str.birthdate, str.beginning)

  end

 end

 # Прочие методы...

end

p1 = Person.new("Rudy",Time.now - (14 * 365 * 86400), 100)

p [p1.name, p1.age, p1.balance] # ["Rudy", 14.0, 197.99315994394]

str = Marshal.dump(p1)

p2 = Marshal.load(str)

p [p2.name, p2.age, p2.balance] # ["Rudy", 14.0, 197.99315994394]

При сохранении объекта этого типа атрибуты age и balance не сохраняются. А когда объект восстанавливается, они вычисляются заново. Заметьте: метод marshal_load предполагает, что объект существует; это один из немногих случаев, когда метод initialize приходится вызывать явно (обычно это делает метод new).