2009-03-27 14 views
17

¿Hay alguna forma de copiar las asociaciones de un modelo a otro ...ActiveRecord: ¿Puedo copiar asociaciones?

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

... de tal manera que copio a los niños de la plantilla para el nuevo modelo? (De hecho, este código mueve a los niños de la plantilla al nuevo modelo).

Sé que puedo hacerlo de forma manual, pero ¿hay alguna forma más concisa?

Gracias

Respuesta

25

El problema es que vaya a clonar la plantilla, pero no es la clonación de los niños. Pruebe algo como:

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

perfecto! Eso es, bonito y conciso. Muchas gracias. – Paul

0

Bueno, no es realmente una copia.

Pero usted podría hacer

new_model.child_ids = template_model.child_ids 
3

Añadir esta algunos donde se encuentra bajo/lib. Por ejemplo, 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 

Crear un nuevo inicializador en config/initializers/folder. Dentro de este archivo pegar

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

Ahora puede clonar el modelo con todas sus asociaciones de has_one y hos_many.

cloned_person = person.clone_deep 
cloned_person.save 
+0

Solo esta simple solución funcionó para mí ... tanto la ameba como las gemas deep_cloneable llamaban por defecto dup y no copiaban asociaciones ... deep_cloneable gem failed on many through..rails 4.1 Gracias – Abs

1

#dup deben utilizarse en lugar de #clone, ya que los atributos no se copian en el caso de este último.

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-dup

Cuestiones relacionadas