Как я могу обновить уже созданный объект Ruby с помощью YAML?

По сути, у меня уже есть экземпляр объекта Ruby, но я хочу обновить любые переменные экземпляра, которые могу, из yaml. Есть функция to_yaml, которая выгружает мой объект в yaml. Я ищу что-то в обратном направлении. Например, my_obj.from_yaml(yaml_stuff) и обновить переменные экземпляра из переданного yaml.

Нужно ли мне в моей функции from_yaml использовать YAML::load и копировать каждую переменную экземпляра? Есть ли функция, которую я могу использовать для быстрого копирования этих переменных без особого ввода, если это так?

Есть ли в библиотеке Ruby yaml уже что-то, куда я могу передать ему объект и yaml, и он просто будет делать то, что я хочу?

Редактирование для ясности

Это простой объект, который будет хранить и загружать очень простые совместимые с yaml типы, такие как строки и целые числа.

Что я в итоге сделал

Хотя я ответил на этот вопрос, я хотел добавить то, что я в итоге сделал, мой патч Object monkey

class Object

  def from_yaml(yml)

    if (yml.nil?)
      return
    end

    yml.instance_variables.each do |iv|
      if (self.instance_variable_defined?(iv))
        self.instance_variable_set(iv, yml.instance_variable_get(iv))
      end
    end

  end
end

person Justin    schedule 10.11.2010    source источник


Ответы (3)


Ваш вопрос недостаточно ясен. О каком классе вы говорите? Какие документы YAML? Вы не можете сериализовать все в YAML и обратно.

Предположим, что ваш объект просто имеет набор переменных экземпляра простых, совместимых с YAML типов, таких как строки, числа и символы.

В этом случае вы обычно можете написать метод from_yaml, который будет загружать файл YAML в хэш из key->value пар, выполнять итерацию по нему и обновлять каждую переменную экземпляра с именем key на value. Кажется ли это полезным, и если да, нужна ли вам помощь в написании такого метода?

Редактировать:

Вам не нужно хранить состояние вашего объекта в хэше — вы все равно можете использовать ivars и attr_accessors — просто откройте новый модуль (скажем, YamlUpdateable), реализуйте метод from_yaml, который будет обновлять ваши ivars из хэша, десериализованного из YAML, и включите модуль в любой класс, который вы хотите десериализовать из YAML.

person Mladen Jablanović    schedule 10.11.2010
comment
Извините, если я был неясен. Члены объекта состоят из очень простых типов, совместимых с YAML. Я не знал, существует ли уже эта функциональность в библиотеке yaml для ruby ​​или мне нужно сделать что-то особенное. Похоже, мне нужно сделать что-то особенное. Возможно, мне придется опубликовать это как другой вопрос, но есть ли преимущество в хранении данных экземпляра в хэше и использовании method_missing для обновления данных? Тогда я могу просто вводить и выводить хэш. - person Justin; 10.11.2010

Насколько мне известно, в самой библиотеке YAML нет ничего подобного; в основном он предназначен для дампа и чтения данных, а не для поддержания их в актуальном состоянии в памяти и на диске. Если вы планируете синхронизировать данные в памяти и на диске друг с другом с минимальными трудностями, рассматривали ли вы библиотеку сохранения данных, например ActiveRecord или Stone?

Если вы все еще заинтересованы в использовании библиотеки YAML и предполагаете, что у вас не так много разных классов для сохранения, может иметь смысл просто написать небольшой метод «обновления», который обновляет объект этого класса, учитывая аналогичный объект. Или вы можете переработать свое приложение, чтобы убедиться, что вы можете просто перезагрузить все объекты из YAML без необходимости их обновления (т. е. выгрузить старые объекты и создать новые).

Другой вариант — использовать метапрограммирование для чтения свойств объекта и их соответствующего обновления, но это кажется подверженным ошибкам и опасным.

person Sérgio Gomes    schedule 10.11.2010

То, что вы ищете, это команда merge.

// fetch yaml file
yml = YAML.load_file("path/to/file.yml")

// merge variables
my_obj.merge(yml)
person sintaxi    schedule 11.11.2010
comment
Не похоже, что в классе объектов есть функция слияния. Однако есть один для хеш-класса. - person Justin; 11.11.2010