Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If you want to get all descendants of a node in a tree-like hierarchy you have two options:</p> <ol> <li><p>Use the classic <code>acts_as_tree</code>, preload the selected category, start a cascade of queries to retrieve all the children, the grandchildren etc, until you get only leaves (nodes without further chidren). This approach is as good as it sounds.</p></li> <li><p>Use a more advanced tree representation, like nested set or closure tree. Under these representation you can get all descendants of a specific node with just one single query. </p></li> </ol> <p>Then you get the collected categories and query in Businesses:</p> <pre><code>Business.where(:category =&gt; categories) </code></pre> <hr> <p><strong>(technical explanation: nested set)</strong></p> <p>Under a nested set representation, each node has two indices, assigned in the following way: imagine that each node is a house with two windows, East and West, and the tree is like a bifurcating road where all children are more or less to the north of their parent. So you start to the east of the root house, and put a sequential number on the windows you meet. You never cross any road, you are only allowed to go around houses which has no further road to the north. At the end you'll get again to the root house, and put a number on the west window.</p> <p>The assigned numbers will have the following properties:</p> <ul> <li>All east windows have even numbers, all west windows have odd numbers (provided you started with 0)</li> <li>The delta in each house (difference between west and east number) is always 1 + the number of descendant houses</li> <li>All descendant houses of any house H will have their east and west numbers strictly included between H's own numbers</li> <li>The converse is true too, all houses whose numbers are strictly comprised between H's numbers are actually descendants of H</li> <li>If two houses are not ancestors one of the other (so one's nombers are comprised between the other's) then they are completely separated, that is both numbers of one house are strictly less than both numbers of the other.</li> </ul> <p>So, while inserting a new element in the tree is costly (it needs to update a number of indices), retrieving the whole descendance (all children, grandchildren, ...) is quite easy, just take the nodes whose "east" and "west" numbers are between your chosen category's east and west. You can actully do slightly better, but it doesn't matter here.</p> <p>A library like <a href="https://github.com/collectiveidea/awesome_nested_set" rel="nofollow">https://github.com/collectiveidea/awesome_nested_set</a> will manage all this for you, and you only call </p> <pre><code>categories = @category.self_and_descendants.to_a </code></pre> <hr> <p><strong>(technical explanation: closure tree)</strong></p> <p>This approach need an accessory table, where you store the transitive closure of the <code>child-&gt;parent</code> relationship (see <a href="http://en.wikipedia.org/wiki/Reflexive_transitive_closure#P_closures_of_binary_relations" rel="nofollow">http://en.wikipedia.org/wiki/Reflexive_transitive_closure#P_closures_of_binary_relations</a> )</p> <p>The table will contain all pairs ancestor-descendant, so you can join in smart ways with that table to get almost any slicing of the hierarchy.</p> <p>Again, a library such as <a href="https://github.com/mceachen/closure_tree" rel="nofollow">https://github.com/mceachen/closure_tree</a> will do the hard work for you, and you will be able to do</p> <pre><code>categories = @category.self_and_descendants.to_a </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload