Module: ActiveRecord::Acts::NestedSet::InstanceMethods

Defined in:
lib/active_record/acts/nested_set.rb

Instance Method Summary collapse

Instance Method Details

#add_child(child) ⇒ Object

Added a child to this object in the tree. If this object hasn’t been initialized, it gets set up as a root node. Otherwise, this method will update all of the other elements in the tree and shift them to the right. Keeping everything balanaced.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/active_record/acts/nested_set.rb', line 141

def add_child( child )     
  self.reload
  child.reload

  if child.root?
    raise "Adding sub-tree isn\'t currently supported"
  else
    if ( (self[left_col_name] == nil) || (self[right_col_name] == nil) )
      # Looks like we're now the root node!  Woo
      self[left_col_name] = 1
      self[right_col_name] = 4
      
      # What do to do about validation?
      return nil unless self.save
      
      child[parent_column] = self.id
      child[left_col_name] = 2
      child[right_col_name]= 3
      return child.save
    else
      # OK, we need to add and shift everything else to the right
      child[parent_column] = self.id
      right_bound = self[right_col_name]
      child[left_col_name] = right_bound
      child[right_col_name] = right_bound + 1
      self[right_col_name] += 2
      self.class.transaction {
        self.class.update_all( "#{left_col_name} = (#{left_col_name} + 2)",  "#{scope_condition} AND #{left_col_name} >= #{right_bound}" )
        self.class.update_all( "#{right_col_name} = (#{right_col_name} + 2)",  "#{scope_condition} AND #{right_col_name} >= #{right_bound}" )
        self.save
        child.save
      }
    end
  end                                   
end

#all_childrenObject

Returns a set of all of it’s children and nested children



188
189
190
# File 'lib/active_record/acts/nested_set.rb', line 188

def all_children
  self.class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} > #{self[left_col_name]}) and (#{right_col_name} < #{self[right_col_name]})" )
end

#before_destroyObject

Prunes a branch off of the tree, shifting all of the elements on the right back to the left so the counts still work.



199
200
201
202
203
204
205
206
207
208
# File 'lib/active_record/acts/nested_set.rb', line 199

def before_destroy
  return if self[right_col_name].nil? || self[left_col_name].nil?
  dif = self[right_col_name] - self[left_col_name] + 1

  self.class.transaction {
    self.class.delete_all( "#{scope_condition} and #{left_col_name} > #{self[left_col_name]} and #{right_col_name} < #{self[right_col_name]}" )
    self.class.update_all( "#{left_col_name} = (#{left_col_name} - #{dif})",  "#{scope_condition} AND #{left_col_name} >= #{self[right_col_name]}" )
    self.class.update_all( "#{right_col_name} = (#{right_col_name} - #{dif} )",  "#{scope_condition} AND #{right_col_name} >= #{self[right_col_name]}" )
  }
end

#child?Boolean

Returns true is this is a child node

Returns:

  • (Boolean)


126
127
128
129
# File 'lib/active_record/acts/nested_set.rb', line 126

def child?                          
  parent_id = self[parent_column]
  !(parent_id == 0 || parent_id.nil?) && (self[left_col_name] > 1) && (self[right_col_name] > self[left_col_name])
end

#children_countObject

Returns the number of nested children of this object.



178
179
180
# File 'lib/active_record/acts/nested_set.rb', line 178

def children_count
  return (self[right_col_name] - self[left_col_name] - 1)/2
end

#direct_childrenObject

Returns a set of only this entries immediate children



193
194
195
# File 'lib/active_record/acts/nested_set.rb', line 193

def direct_children
  self.class.find(:all, :conditions => "#{scope_condition} and #{parent_column} = #{self.id}")
end

#full_setObject

Returns a set of itself and all of it’s nested children



183
184
185
# File 'lib/active_record/acts/nested_set.rb', line 183

def full_set
  self.class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} BETWEEN #{self[left_col_name]} and #{self[right_col_name]})" )
end

#root?Boolean

Returns true is this is a root node.

Returns:

  • (Boolean)


120
121
122
123
# File 'lib/active_record/acts/nested_set.rb', line 120

def root?
  parent_id = self[parent_column]
  (parent_id == 0 || parent_id.nil?) && (self[left_col_name] == 1) && (self[right_col_name] > self[left_col_name])
end

#unknown?Boolean

Returns true if we have no idea what this is

Returns:

  • (Boolean)


132
133
134
# File 'lib/active_record/acts/nested_set.rb', line 132

def unknown?
  !root? && !child?
end