Моя рекурсивная функция не заканчивается.Что я делаю неправильно? - PullRequest
0 голосов
/ 18 апреля 2011

У меня есть модель под названием папка, которая действует как дерево.Внутри модели у меня есть экземпляр метода экземпляра, который копирует папки из одного места в другое.При копировании папки также необходимо скопировать ее подпапки.

Это мой код:

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

Теперь рассмотрим следующую ситуацию:

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

Когда я копирую папку 1 в корневую папку, она работает нормально.Это также работает, когда я копирую папку 1 в папку 2, но когда я копирую папку 1 в папку 3, я получаю бесконечную рекурсию.В коде:

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

Этот код приводит к:

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

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

Ответы [ 3 ]

1 голос
/ 18 апреля 2011

Попробуйте изменить порядок вашего метода так, чтобы он сначала достиг конечного узла, прежде чем выполнять рекурсию:

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

Ваша проблема в том, что вы начинаете с того, что переименовываете «Папка 1» в «Папка 3». Тогда ваш рекурсивный вызов запускается. Когда он попадает в «Папку 3», он становится «Папкой 1» в качестве дочернего элемента, и цикл продолжается.

0 голосов
/ 18 апреля 2011

Я должен был отслеживать, какую папку я изначально скопировал.Код ниже работает.Конечно, если кто-то видит возможности для улучшения, пожалуйста, дайте мне знать.

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 голосов
/ 18 апреля 2011

Попробуйте выполнить копирование текущей папки перед циклом, который реализует рекурсию (т.е. рекурсию предварительного заказа).

...