-1

ツリーとして機能するfolderというモデルがあります。モデル内には、フォルダーをある場所から別の場所にコピーするインスタンスメソッドのコピーがあります。フォルダをコピーするときは、そのサブフォルダもコピーする必要があります。

これは私のコードです:

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.

些細なことを見落としていますが、理解できません。私は何が間違っているのですか?

4

3 に答える 3

1

再帰を実行する前に、メソッドの順序を変更して、最初にリーフノードに到達するようにしてください。

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

問題は、「フォルダ3」の下の「フォルダ1」の親を変更することから始めていることです。次に、再帰呼び出しが実行されます。「フォルダ3」に到達すると、子として「フォルダ1」が作成され、サイクルが続行されます。

于 2011-04-17T23:51:36.933 に答える
0

再帰を実装するループの前に、現在のフォルダーのコピーを実行してみてください(つまり、事前注文の再帰)。

于 2011-04-17T23:33:21.320 に答える
0

最初にコピーしたフォルダを追跡する必要がありました。以下のコードは機能します。もちろん、改善の余地があると思われる方がいらっしゃいましたら、お知らせください。

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
于 2011-04-17T23:52:22.090 に答える