ActiveRecord: могу ли я копировать ассоциации? - PullRequest
17 голосов
/ 27 марта 2009

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

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

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

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

Спасибо

Ответы [ 4 ]

27 голосов
/ 27 марта 2009

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

template_model = MyModel.find(id)
new_model = template_model.clone
new_model.children << template_model.children.collect { |child| child.clone }
4 голосов
/ 18 октября 2013

Добавьте это где-нибудь в / 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
1 голос
/ 30 сентября 2015

#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

0 голосов
/ 27 марта 2009

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

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

new_model.child_ids = template_model.child_ids
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...