0

私は素晴らしいawesome_nestedセットで作られたカテゴリモデルを持っています. ドラッグ アンド ドロップ ツリーを正常に生成し、SERIALIZELIST プラグインを使用してこのツリーの完全なハッシュを正常に生成し、カテゴリ コントローラーに追加した「配列」メソッドに送信しました。(jqueryとnestedsortablesを使用)ログからのハッシュは次のようになります...

処理中 CategoriesController#array (2010-08-19 23:12:18 の 127.0.0.1 の場合) [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つの関数を書くことになりました。1 つは配列のルートを通過し、もう 1 つは子と子の子を再帰的に移動します。しかし、これはあまりにも多くのデータベース呼び出しで終わります (しかし、それを行う方法は他にないかもしれません)。

コードは次のようになります...

  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 プラグイン ....

乾杯、

マテニア

4

2 に答える 2

3

最終的な回避策については、上記の編集された質問を参照してください..コードを github に投稿しました..ただし、いくつかのバグがあり、リファクタリングが必要な場合があります。 JQUERY ネストされた SORTABLES - ドラッグ アンド ドロップ - すばらしいネストされたセット

更新: 少しきれいなコードでレポに Rails 3 の例を追加しました

于 2010-11-05T14:01:07.480 に答える
0

Rails 2.3 アプリを 3.1 にアップグレードすると、同じ問題が発生しました。私の場合、1 つの深さ (ルートかどうか) だけをソートしたかったのです。これが私が最終的に得たものです:

# Fetch all IDs (they will be in order)
ids = params[:sort].collect { |param| param[/^page_(\d+)$/, 1] }
# Remove first item from array, moving it to left of first sibling
prev = Page.find(ids.shift)
prev.move_to_left_of(prev.siblings.first)
# Iterate over remaining IDs, moving to the right of previous item
ids.each_with_index { |id, position| current = Page.find(id); current.move_to_right_of(prev); prev = current }
于 2011-11-15T10:54:07.397 に答える