Подтвердить что ты не робот

ActiveRecord: Могу ли я копировать ассоциации?

Есть ли способ скопировать ассоциации одной модели в другую...

template_model = MyModel.find(id)
new_model = template_model.clone
new_model.children << template_model.children # I want to *copy* children

... такое, что я копирую детей из шаблона в новую модель? (На самом деле этот код перемещает детей из шаблона в новую модель).

Я знаю, что я могу это сделать вручную, но есть ли более краткий путь?

Спасибо

4b9b3361

Ответ 1

Проблема в том, что вы клонируете шаблон, но не клонируете его детям. Попробуйте что-то вроде:

template_model = MyModel.find(id)
new_model = template_model.clone
new_model.children << template_model.children.collect { |child| child.clone }

Ответ 2

Добавьте это, где находится под /lib. Например clone_deep.rb.

module CloneDeep
  def clone_deep
    kopy = clone
    self.class.reflect_on_all_associations.each do |association|
      next if association.macro == :belongs_to
      cloned_object = case association.macro
                        when :has_many
                          self.send(association.name).collect { |item| item.clone_deep }
                        when :has_one
                          self.send(association.name) && self.send(association.name).clone_deep
                        else
                          clone
                      end
      kopy.send("#{association.name}=", cloned_object)
    end
    return kopy
  end
end

Создайте новый инициализатор в папке config/initializers/. Внутри этого файла вставьте

ActiveRecord::Base.send(:include, CloneDeep)

Теперь вы можете клонировать модель со всеми ее has_one и ассоциациями hos_many.

cloned_person = person.clone_deep
cloned_person.save

Ответ 3

#dup следует использовать вместо #clone, поскольку атрибуты не копируются в случае последнего.

module Promotion
  class Banner
    has_many :localizations
    has_many :images

    def deep_dup!
      duplicate = dup
      duplicate.save

      duplicate.localizations = localizations.collect { |localization| localization.dup }
      duplicate.images = images.collect { |image| image.dup }

      duplicate
    end
  end
end

http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-i-clone http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-i-dup

Ответ 4

Ну, это не совсем копия.

Но вы могли бы сделать

new_model.child_ids = template_model.child_ids