2011-04-17 5 views
-1

J'ai un modèle appelé dossier qui agit comme un arbre. Dans le modèle, j'ai une copie de méthode d'instance qui copie les dossiers d'un endroit à l'autre. Lors de la copie d'un dossier, ses sous-dossiers doivent également être copiés.Ma fonction récursive ne se termine pas. Qu'est-ce que je fais mal?

Ceci est mon code:

class Folder < ActiveRecord::Base 
    acts_as_tree :order => 'name' 
    before_save :check_for_parent 

    def copy(target_folder) 
    new_folder = self.clone 
    new_folder.parent = target_folder 
    new_folder.save! 

    # Copy sub-folders recursively 
    self.children.each do |folder| 
     folder.copy(new_folder) unless folder == new_folder 
    end 
    end 

    def check_for_parent 
    raise 'Folders must have a parent.' if parent.nil? && name != 'Root folder' 
    end 
end 

Considérons maintenant la situation suivante:

Root folder-+ 
      | 
     Folder 1-+ 
        | 
       Folder 2-+ 
         | 
         Folder 3 

Lorsque je copie le dossier 1 dans le dossier racine il fonctionne très bien. Cela fonctionne également quand je copie le dossier 1 dans le dossier 2, mais quand je copie le dossier 1 dans le dossier 3 je finis avec la récursivité sans fin. Dans le code:

f1 = Folder.find_by_name('Folder 1') 
f3 = Folder.find_by_name('Folder 3') 
f1.copy(f3) # Never stops 

Ce code conduit à:

Root folder-+ 
      | 
     Folder 1-+ 
        | 
       Folder 2-+ 
         | 
         Folder 3-+ 
           | 
          Folder 1-+ 
            | 
            Folder 2-+ 
              | 
             Folder 3-+ 
                | 
               Folder 1-+ 
                 | 
                Folder 2-+ 
                   | 
                  Folder 3-+ 
                    | 
                    Folder 1-+ 
                      | 
                      Etc. 

je donne sur quelque chose de trivial, mais je ne peux pas le comprendre. Qu'est-ce que je fais mal??

Répondre

0

Je devais garder une trace du dossier que j'avais initialement copié. Le code ci-dessous fonctionne. Bien sûr, si quelqu'un voit une amélioration, merci de me le faire savoir.

def copy(target_folder, originally_copied_folder = nil) 
    new_folder = self.clone 
    new_folder.parent = target_folder 
    new_folder.save! 

    originally_copied_folder = new_folder if originally_copied_folder.nil? 

    # Copy sub-folders recursively 
    self.children.each do |folder| 
     folder.copy(new_folder, originally_copied_folder) unless folder == originally_copied_folder 
    end 
    end 
0

Essayez d'effectuer la copie du dossier actuel avant la boucle qui implémente la récursivité (c'est-à-dire la récursivité de précommande).

+0

Que voulez-vous dire exactement? Il semble que je fais déjà la copie du dossier en cours avant la boucle. (Dans les trois premières lignes de la méthode) Pourriez-vous me montrer du code? Je vous remercie! – Mischa

+0

Désolé, je voulais dire "après". – Marcin

1

Essayez de changer l'ordre de votre méthode afin qu'il atteigne le nœud de la première feuille, avant de faire votre récursion:

def copy(target_folder) 
    new_folder = self.clone 

    # Copy sub-folders recursively 
    self.children.each do |folder| 
    folder.copy(new_folder) unless folder == new_folder 
    end 

    new_folder.parent = target_folder 
    new_folder.save! 
end 

Votre problème est que vous commencez par reparentage « Dossier 1 » sous « dossier 3 '. Ensuite, votre appel récursif s'exécute. Quand il arrive à 'Dossier 3' il a maintenant 'Dossier 1' comme un enfant, et le cycle continue.

+0

Merci. Oui, j'ai déjà essayé, mais dans ce cas, je reçois une erreur à cause du 'before_save'. Cela aurait probablement dû être plus clair dans ma question. – Mischa

Questions connexes