2009-03-27 13 views
17

Gibt es eine Möglichkeit, die Assoziationen von einem Modell zum anderen ...ActiveRecord: Kann ich Assoziationen kopieren?

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

... so dass ich die Kinder aus der Vorlage in das neue Modell kopieren zu kopieren? (In der Tat verschiebt dieser Code Kinder von der Vorlage zum neuen Modell).

Ich weiß, ich kann es manuell machen Schleifen sein, aber gibt es prägnanter Weg?

Dank

Antwort

25

Das Problem ist, dass Sie die Vorlage klonen, aber es ist Kinder nicht klonen. Versuchen Sie etwas wie:

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

Perfect! Das ist es - nett und prägnant. Vielen Dank. – Paul

0

Nun, es ist nicht wirklich eine Kopie.

Aber man konnte tun

new_model.child_ids = template_model.child_ids 
3

dies einige hinzufügen, wo unter/lib ist. Zum Beispiel 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 

Neuen initializer unter config/initializers/Ordner. Innerhalb dieser Datei einfügen

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

Jetzt können Sie Modell mit allen es ist has_one und hos_many Assoziationen zu klonen.

cloned_person = person.clone_deep 
cloned_person.save 
+0

Nur diese einfache Lösung funktionierte für mich .. beide Amöben und deep_cloneable Edelsteine ​​waren standardmäßig Aufruf von dup und nicht Kopieren von Assoziationen .. deep_cloneable gem gescheitert auf hat viele through..rails 4.1 Danke – Abs

1

#dup sollte statt #clone verwendet werden, da Attribute in letzterem Fall nicht kopiert werden.

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

Verwandte Themen