我有一个用很棒的 awesome_nested 集制作的类别模型。我已经成功地生成了拖放树,并使用 SERIALIZELIST 插件成功地生成了该树的完整哈希,并将其发送到我添加到类别控制器中的“数组”方法。(使用jquery和nestedsortables)我的日志中的哈希看起来像这样......
处理 CategoriesController#array (for 127.0.0.1 at 2010-08-19 23:12:18) [POST] 参数:{"ul"=>{"0"=>{"class"=>"", "id" =>"category_1", "children"=>{"0"=>{"class"=>"", "id"=>"category_4", "children"=>{"0"=>{"class" =>"", "id"=>"category_3"}}}}}, "1"=>{"class"=>"", "id"=>"category_2", "children"=>{"0 "=>{"class"=>"", "id"=>"category_5"}, "1"=>{"class"=>"", "id"=>"category_6"}}}}}
我只是在使用排序功能时遇到了麻烦。
很棒的嵌套集确实提供了一些移动功能,但我似乎无法理解它。
当用户点击保存时,我想做这样的事情(顺便说一句,它执行 ajax 请求并正确传递上述数据)
def array
newlist = params[:ul]
newlist.each_with_index do |id, index, children|
#insert code here for saving the re-ordered array
end
render :nothing => true
end
我希望这是足够的信息,并希望有人可以回答这个问题。
干杯,
马特尼亚
------------ 更新和进展 ------------
自从几天前发布此内容以来,我在我的开发环境中使用 logger.info 来查看幕后发生的事情。
我最终写了2个函数。一个遍历数组的根,另一个递归地将孩子和孩子的孩子移动到位。但这最终会导致太多的数据库调用(尽管可能没有其他方法可以做到)。
代码看起来像这样......
def array
# fetch the current tree
@allcategories = Category.all
# assign the sorted tree to a variable
newlist = params[:ul]
# initialize the previous item
previous = nil
#loop through each item in the new list (passed via ajax)
newlist.each_with_index do |array, index|
# get the category id of the item being moved
moved_item_id = array[1][:id].split(/category_/)
# find the object that is being moved (in database)
@current_category = Category.find_by_id(moved_item_id)
# if this is the first item being moved, move it to the root.
unless previous.nil?
@previous_item = Category.find_by_id(previous)
@current_category.move_to_right_of(@previous_item)
else
@current_category.move_to_root
end
# then, if this item has children we need to loop through them
unless array[1][:children].blank?
# unless there are no children in the array, send it to the recursive children function
childstuff(array[1], @current_category)
end
# set previous to the last moved item, for the next round
previous = moved_item_id
end
render :nothing => true
end
def childstuff(node, category)
# find the category that has been passed into the function
@selected_category = Category.find(category)
for child in node[:children]
child_id = child[1][:id].split(/category_/)
child_category = Category.find_by_id(child_id)
child_category.move_to_child_of(@selected_category)
#if this child has children -- run recursion on this function
unless child[1][:children].blank?
childstuff(child[1], child_category)
end
end
end
我希望有人可以阐明如何提高效率以及如何减少数据库调用的数量。我曾考虑过编写其他函数,但它们都会做同样的事情。
对于这个特定的项目,我不相信会有超过 100 个不同的类别。这不是最好的方法,但它确实有效。
再次欢呼,
马特尼亚
最后的解决方法
我对上面的代码有一个问题,它没有正确地保存孩子。这是我最近的尝试,似乎效果很好。
def array
# assign the sorted tree to a variable
newlist = params[:ul]
# initialize the previous item
previous = nil
#loop through each item in the new list (passed via ajax)
newlist.each_with_index do |array, index|
# get the category id of the item being moved
moved_item_id = array[1][:id].split(/category_/)
# find the object that is being moved (in database)
@current_category = Category.find_by_id(moved_item_id)
# if this is the first item being moved, move it to the root.
unless previous.nil?
@previous_item = Category.find_by_id(previous)
@current_category.move_to_right_of(@previous_item)
else
@current_category.move_to_root
end
# then, if this item has children we need to loop through them
unless array[1][:children].blank?
# NOTE: unless there are no children in the array, send it to the recursive children function
childstuff(array[1], @current_category)
end
# set previous to the last moved item, for the next round
previous = moved_item_id
end
Category.rebuild!
render :nothing => true
end
def childstuff(mynode, category)
# logger.info "node = #{node} caegory = #{category}"
#loop through it's children
for child in mynode[:children]
# get the child id from each child passed into the node (the array)
child_id = child[1][:id].split(/category_/)
#find the matching category in the database
child_category = Category.find_by_id(child_id)
#move the child to the selected category
child_category.move_to_child_of(category)
# loop through the children if any
unless child[1][:children].blank?
# if there are children - run them through the same process
childstuff(child[1], child_category)
end
end
end
仍然有太多的数据库调用,但我想这是想要这个功能所要付出的代价,因为它需要重新记录数据库中的每个项目。
希望这可以帮助其他有需要的人。如果有人需要这方面的帮助,请随时给我发信息。
真棒嵌套集 + JQUERY 拖放 + SERIALIZELIST 插件....
干杯,
马特尼亚