Changeset 2

Show
Ignore:
Timestamp:
08/06/06 15:38:17 (2 years ago)
Author:
jcm
Message:

comments added

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/better_nested_set.rb

    r1 r2  
    77      end   
    88 
     9      # better_nested_set ehances the core nested_set tree functionality provided in ruby_on_rails. 
     10      # 
    911      # This acts provides Nested Set functionality. Nested Set is a smart way to implement 
    1012      # an _ordered_ tree, with the added feature that you can select the children and all of their  
     
    1517      # commercial categories) or an efficient way of querying big trees (threaded posts). 
    1618      # 
    17       # See http://www.dbmsmag.com/9603d06.html for nested sets theory, and a tutorial here: 
    18       # http://threebit.net/tutorials/nestedset/tutorial1.html 
    19       # 
    20       # ===== Small nested set theory reminder: 
    21       # Instead of picturing a leaf node structure with children pointing back to their parent, 
    22       # the best way to imagine how this works is to think of the parent entity surrounding all 
    23       # of its children, and its parent surrounding it, etc.  Assuming that they are lined up 
    24       # horizontally, we store the left and right boundries in the database. 
    25       # 
    26       # Imagine: 
    27       #   root 
    28       #     |_ Child 1 
    29       #       |_ Child 1.1 
    30       #       |_ Child 1.2 
    31       #     |_ Child 2 
    32       #       |_ Child 2.1 
    33       #       |_ Child 2.2 
    34       # 
    35       # If my cirlces in circles description didn't make sense, check out this sweet 
    36       # ASCII art: 
    37       # 
    38       #     ___________________________________________________________________ 
    39       #    |  Root                                                             | 
    40       #    |    ____________________________    ____________________________   | 
    41       #    |   |  Child 1                  |   |  Child 2                  |   | 
    42       #    |   |   __________   _________  |   |   __________   _________  |   | 
    43       #    |   |  |  C 1.1  |  |  C 1.2 |  |   |  |  C 2.1  |  |  C 2.2 |  |   | 
    44       #    1   2  3_________4  5________6  7   8  9_________10 11_______12 13  14 
    45       #    |   |___________________________|   |___________________________|   | 
    46       #    |___________________________________________________________________|  
    47       # 
    48       # The numbers represent the left and right boundries.  The table then might 
    49       # look like this: 
    50       #    ID | PARENT | LEFT | RIGHT | DATA 
    51       #     1 |      0 |    1 |    14 | root 
    52       #     2 |      1 |    2 |     7 | Child 1 
    53       #     3 |      2 |    3 |     4 | Child 1.1 
    54       #     4 |      2 |    5 |     6 | Child 1.2 
    55       #     5 |      1 |    8 |    13 | Child 2 
    56       #     6 |      5 |    9 |    10 | Child 2.1 
    57       #     7 |      5 |   11 |    12 | Child 2.2 
    58       # 
    59       # So, to get all children of an entry, you 
    60       #     SELECT * WHERE CHILD.LEFT IS BETWEEN PARENT.LEFT AND PARENT.RIGHT 
    61       # 
    62       # To get the count, it's (LEFT - RIGHT + 1)/2, etc. 
    63       # 
    64       # To get the direct parent, it falls back to using the PARENT_ID field.    
    65       # 
    66       # There are instance methods for all of these. 
    67       # 
    68       # ======= 
    69       # 
     19      # == API 
    7020      # Methods names are aligned on Tree's ones as much as possible, to make replacment from one  
    71       # by another easier, except for the root.children.create("name" => "child1") syntax, because  
    72       # we would have to mimic AssociationCollection behaviour, and that's a bit hard ;-) 
     21      # by another easier, except for the creation: 
    7322      #  
    74       # Here is an example on how to use it: 
    75       #   class Category < ActiveRecord::Base 
    76       #     acts_as_nested_set 
    77       #   end 
    78       # 
    79       #   root = Category.create() 
     23      # in acts_as_tree: 
     24      #   item.children.create(:name => "child1") 
     25      # 
     26      # in acts_as_nested_set: 
     27      #   # adds a new item at the "end" of the tree, i.e. with child.left = max(tree.right)+1 
     28      #   child = MyClass.new(:name => "child1") 
     29      #   child.save 
     30      #   # now move the item to its right place 
     31      #   child.move_to_child_of my_item 
     32      # 
     33      # You can use: 
     34      # * move_to_child_of 
     35      # * move_to_right_of 
     36      # * move_to_left_of 
     37      # and pass them an id or an object. 
     38      # 
     39      # Other methods added by this mixin are: 
     40      # * +root+ - root item of the tree (the one that has a nil parent; should have left_column = 1 too) 
     41      # * +roots+ - root items, in case of multiple roots (the ones that have a nil parent) 
     42      # * +level+ - number indicating the level, a root being level 0 
     43      # * +ancestors+ - array of all parents, with root as first item 
     44      # * +self_and_ancestors+ - array of all parents and self 
     45      # * +siblings+ - array of all siblings, that are the items sharing the same parent and level 
     46      # * +self_and_siblings+ - array of itself and all siblings 
     47      # * +children_count+ - count of all immediate children 
     48      # * +children+ - array of all immediate childrens 
     49      # * +all_children+ - array of all children and nested children 
     50      # * +full_set+ - array of itself and all children and nested children 
     51      # 
     52      # These should not be useful, except if you want to write direct SQL: 
     53      # * +left_col_name+ - name of the left column passed on the declaration line 
     54      # * +right_col_name+ - name of the right column passed on the declaration line     
     55      # * +parent_col_name+ - name of the parent column passed on the declaration line 
     56      # 
     57      # recommandations: 
     58      # Don't name your left and right columns 'left' and 'right': these names are reserved on most of dbs. 
     59      # Usage is to name them 'lft' and 'rgt' for instance. 
    8060      # 
    8161      module ClassMethods                       
     
    151131         
    152132        # Returns true if we have no idea what this is 
     133        # 
     134        # Deprecated, will be removed in next versions 
    153135        def unknown? 
    154136          !root? && !child? 
     
    164146        # other elements in the tree and shift them to the right, keeping everything 
    165147        # balanced.  
     148        # 
     149        # Deprecated, will be removed in next versions 
    166150        def add_child( child )      
    167151          self.reload