我有一个名为文件夹的模型,它充当树。在模型中,我有一个实例方法副本,可以将文件夹从一个地方复制到另一个地方。复制文件夹时,还必须复制其子文件夹。
这是我的代码:
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.
我忽略了一些微不足道的事情,但我无法弄明白。我做错了什么?
答案 0 :(得分: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'作为孩子,并且循环继续。
答案 1 :(得分:0)
尝试在实现递归的循环之前复制当前文件夹(即预订递归)。
答案 2 :(得分: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