Изменение класса объекта в ActiveRecord - PullRequest
5 голосов
/ 09 июля 2010

Допустим, у меня есть объект FireNinja < Ninja в моей базе данных, хранящийся с использованием наследования одной таблицы. Позже я понимаю, что он действительно WaterNinja < Ninja. Какой самый чистый способ изменить его на другой подкласс? Более того, я хотел бы создать новый объект WaterNinja и просто заменить старый FireNinja в БД, сохранив идентификатор.

Редактировать Я знаю, как создать новый объект WaterNinja из моего существующего FireNinja, и я также знаю, что могу удалить старый и сохранить новый. То, что я хотел бы сделать, это mutate класс существующего элемента. Делаю ли я это, создавая новый объект и применяя магию ActiveRecord для замены строки, или делая какие-то безумные вещи с самим объектом, или даже удаляя его и вставляя заново с тем же идентификатором, это часть вопроса.

Ответы [ 4 ]

8 голосов
/ 06 ноября 2011

Вы можете заставить свой FireNinja действовать как WaterNinja, выполнив

@ninja.becomes(WaterNinja)

Если вы хотите навсегда изменить классы, просто перезапишите атрибут type.

@ninja.type = "WaterNinja"
@ninja.save!
2 голосов
/ 09 июля 2010

Вам нужно сделать две вещи:

  • Создать WaterNinja < Ninja
  • В ninjas таблица запустить что-то вроде UPDATE ninjas SET (type = 'WaterNinja') WHERE (type = 'FireNinja')

Этооб этом.

Для выполнения преобразования во время выполнения это будет сделано, но я не рекомендую.

class Ninja
  def become_another_ninja(new_ninja_type)
    update_attribute(:type, new_ninja_type)
    self.class.find(id)
  end
end

@water_ninja = @fire_ninja.become_another_ninja('WaterNinja')

Проблема в том, что @fire_ninja теперь будет выбрасывать объект.

0 голосов
/ 09 июля 2010

Сочетание композиции с наследованием - вы должны использовать шаблон стратегии, чтобы изменить этот тип поведения во время выполнения.

http://en.wikipedia.org/wiki/Strategy_pattern

0 голосов
/ 09 июля 2010

Вам нужно будет определить метод WaterNinja#to_fireninja.У Ruby нет способа изменить класс объекта, сохранив тот же объект.

class WaterNinja < Ninja
  def to_fireninja
    FireNinja.new :name => name
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...