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

10.2.3. Ограниченное «глубокое копирование» в ходе маршалинга

В Ruby нет операции «глубокого копирования». Методы dup и clone не всегда работают, как ожидается. Объект может содержать ссылки на вложенные объекты, а это превращает операцию копирования в игру «собери палочки».

Ниже предлагается способ реализовать глубокое копирование с некоторыми ограничениями, обусловленными тем, что наш подход основан на использовании класса Marshal со всеми присущими ему недостатками:

def deep_copy(obj)

 Marshal.load(Marshal.dump(obj))

end

a = deep_copy(b)

10.2.4. Обеспечение устойчивости объектов с помощью библиотеки PStore

Библиотека PStore реализует хранение объектов Ruby в файле. Объект класса PStore может содержать несколько иерархий объектов Ruby. У каждой иерархии есть корень, идентифицируемый ключом. Иерархии считываются с диска в начале транзакции и записываются обратно на диск в конце.

require 'pstore'

# Сохранить.

db = PStore.new('employee.dat') db.transaction do

 db['params'] = {'name' => 'Fred', 'age' => 32,

                 'salary' => 48000 }

end

# Восстановить.

require 'pstore'

db = Pstore.new('employee.dat')

emp = nil

db.transaction { emp = db['params'] }

Обычно внутри блока транзакции используется переданный ему объект PStore. Но можно получить и сам вызывающий объект, как показано в примере выше.

Эта техника ориентирована на транзакции; в начале блока обрабатываемые данные читаются с диска. А в конце прозрачно для программиста записываются на диск.

Мы можем завершить транзакцию досрочно, вызвав метод commit или abort. В первом случае все изменения сохраняются, во втором отбрасываются. Рассмотрим более длинный пример:

require 'pstore'

# Предполагается, что существует файл с двумя объектами.

store = PStore.new('objects')

store.transaction do |s|

 a = s['my_array'] h = s['my_hash']

 # Опущен воображаемый код, манипулирующий объектами

 # a, h и т. д.

 # Предполагается, что переменная 'condition' может

 # принимать значения 1, 2, 3...

 case condition

  when 1

   puts 'Отмена.'

   s.abort # Изменения будут потеряны.

  when 2

   puts 'Фиксируем и выходим.'

   s.commit # Изменения будут сохранены.

  when 3

   # Ничего не делаем...

 end

 puts 'Транзакция дошла до конца.'

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату