8

awesome_nested_setRails プロジェクトでプラグインを使用しています。次のような 2 つのモデルがあります (簡略化)。

class Customer < ActiveRecord::Base
  has_many :categories
end

class Category < ActiveRecord::Base
  belongs_to :customer

  # Columns in the categories table: lft, rgt and parent_id
  acts_as_nested_set :scope => :customer_id

  validates_presence_of :name
  # Further validations...
end

データベース内のツリーは期待どおりに構築されます。parent_idlftおよびのすべての値rgtは正しいです。ツリーには複数のルート ノードがあります (これはもちろん で許可されていawesome_nested_setます)。

<ul>ここで、特定の顧客のすべてのカテゴリを、構造のような正しくソートされたツリー (ネストされたタグなど) にレンダリングしたいと考えています。これはそれほど難しくありませんが、効率的である必要があります (SQL クエリが少ないほど良い)。

更新: SQL クエリをさらに実行しなくても、ツリー内の任意のノードの子の数を計算できることがわかりました: number_of_children = (node.rgt - node.lft - 1)/2. これで問題が解決するわけではありませんが、役に立つかもしれません。

4

7 に答える 7

5

2009 年 9 月以降、すばらしいネストされたセットには、これを行うための特別な方法が含まれています :

この方法は、追加のデータベース クエリを必要としないため、呼び出しレベルよりもはるかに効率的です。

例: Category.each_with_level(Category.root.self_and_descendants) do |o, level|

于 2011-02-11T15:03:50.583 に答える
5

最近、php に関する同様の質問に回答しました(ネストされたセット == 変更された事前注文ツリー トラバーサル モデル)。

基本的な概念は、1 つの SQL クエリを使用して、既に順序付けされた深度インジケーターを使用してノードを取得することです。そこからはループや再帰を経由して出力をレンダリングするだけなので、これをルビに変換するのは簡単なはずです。

私はawesome_nested_setプラグインに精通していませんが、ネストされたセットを扱うときはかなり標準的な操作/必要であるため、深さの注釈が付けられ、順序付けられた結果を取得するオプションが既に含まれている可能性があります。

于 2009-09-03T18:35:07.740 に答える
3

自分自身を呼び出すパーシャルを再帰的にレンダリングする必要があります。このようなもの:

# customers/show.html.erb
<p>Name: <%= @customer.name %></p>
<h3>Categories</h3>
<ul>
  <%= render :partial => @customer.categories %>
</ul>

# categories/_category.html.erb
<li>
  <%= link_to category.name, category %>
  <ul>
    <%= render :partial => category.children %>
  </ul>
</li>

これは Rails 2.3 のコードです。その前に、ルートを呼び出して部分的に明示的に名前を付ける必要があります。

于 2009-09-03T12:30:25.223 に答える
3

_tree.html.eb

@set = Category.root.self_and_descendants
<%= render :partial => 'item', :object => @set[0] %>

_item.html.erb

<% @set.shift %>
<li><%= item.name %>
<% unless item.leaf? %>
<ul>
  <%= render :partial => 'item', :collection => @set.select{|i| i.parent_id == item.id} %>
</ul>
<% end %>
</li>

また、それらを並べ替えることができます:

  <%= render :partial => 'item', :collection => @set.select{|i| i.parent_id == item.id}.sort_by(&:name) %>

ただし、その場合は、次の行を削除する必要があります。

<% @set.shift %>
于 2010-06-16T10:38:02.247 に答える
1

それが書かれた古いバージョンのルビーのために、私は受け入れられた答えを得ることができなかったと思います。これが私のために働く解決策です:

def tree_from_set(set)
    buf = ''

    depth = -1
    set.each do |node|
        if node.depth > depth
            buf << "<ul><li>#{node.title}"
        else
            buf << "</li></ul>" * (depth - node.depth)
            buf << "</li><li>#{node.title}"
        end

        depth = node.depth
    end

    buf << "</li></ul>" * (depth + 1)

    buf.html_safe
end

オプションの深度情報を使用することで簡略化されます。(このアプローチの利点は、入力セットが葉の構造全体である必要がないことです。)

深さのないより複雑なソリューションは、gem の github wiki にあります。

https://github.com/collectiveidea/awesome_nested_set/wiki/How-to-generate-nested-unordered-list-tags-with-one-DB-hit

于 2014-06-15T20:16:13.310 に答える