Module: FastTree::Model

Extended by:
ActiveSupport::Concern
Defined in:
lib/fast_tree.rb,
lib/fast_tree/model.rb,
lib/fast_tree/model/subtree/traverse.rb

Defined Under Namespace

Modules: ClassMethods, Subtree Classes: InvalidTreeStructureError

Instance Method Summary collapse

Instance Method Details

#add_child(node) ⇒ Object

Instance Methods



148
149
150
151
152
153
154
155
156
157
# File 'lib/fast_tree/model.rb', line 148

def add_child(node)
  # bulk update nodes by a sql query
  _update_nodes(r_ptr, r_ptr, "r_ptr >= #{r_ptr}")

  # child node's pointer
  node.l_ptr = r_ptr
  node.r_ptr = r_ptr + 1
  node.depth = depth + 1
  node.save
end

#copy_to(node) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/fast_tree/model.rb', line 170

def copy_to(node)
  subtree = self.class.find_subtree_by_root(self)

  # create empty space into which subtree embedded
  _update_nodes(node.l_ptr, node.r_ptr, "r_ptr >= #{r_ptr}", width + 1)

  bias = node.l_ptr + 1 - l_ptr
  base_depth = depth
  subtree.each do |st_node|
    attributes = st_node.attributes.to_h
    attributes.delete("id")
    attributes["l_ptr"] += bias
    attributes["r_ptr"] += bias
    attributes["depth"] += node.depth - base_depth + 1
    self.class.create(attributes)
  end
end

#create_child(attributes = {}, &block) ⇒ Object



159
160
161
162
163
164
165
166
167
168
# File 'lib/fast_tree/model.rb', line 159

def create_child(attributes = {}, &block)
  # bulk update nodes by a sql query
  _update_nodes(r_ptr, r_ptr, "r_ptr >= #{r_ptr}")

  # create child
  attributes[:l_ptr] = r_ptr
  attributes[:r_ptr] = r_ptr + 1
  attributes[:depth] = depth + 1
  self.class.create(attributes, &block)
end

#has_children?Boolean



252
253
254
# File 'lib/fast_tree/model.rb', line 252

def has_children?
  l_ptr != r_ptr - 1
end

#leaf?Boolean



248
249
250
# File 'lib/fast_tree/model.rb', line 248

def leaf?
  l_ptr == r_ptr - 1
end

#move_to(node) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/fast_tree/model.rb', line 188

def move_to(node)
  # NOTE:
  # copy_to and remove change node ids
  # move operation should change nothing but left and right pointers

  # bind subtree to a variable
  subtree = self.class.find_subtree_by_root(self)

  # fill (virtual) empty spaces that will be created by moving subtree
  _update_nodes(l_ptr, r_ptr, "l_ptr > #{r_ptr}", - (width + 1))

  # create empty spaces under the node
  node.reload
  _update_nodes(node.l_ptr, node.r_ptr, "l_ptr >= #{node.l_ptr} AND r_ptr <= #{node.r_ptr}", width + 1)

  # move subtree under the given node
  bias = node.l_ptr + 1 - l_ptr
  base_depth = depth
  subtree.each do |st_node|
    st_node.l_ptr += bias
    st_node.r_ptr += bias
    st_node.depth += node.depth - base_depth + 1
    st_node.save
  end
end

#pathObject



225
226
227
228
229
# File 'lib/fast_tree/model.rb', line 225

def path
  self.class.where(self.class.arel_table[:l_ptr].lteq(l_ptr))
            .where(self.class.arel_table[:r_ptr].gteq(r_ptr))
            .order(l_ptr: :asc)
end


231
232
233
# File 'lib/fast_tree/model.rb', line 231

def print_subtree
  self.class.print_subtree(self)
end

#removeObject



214
215
216
217
218
219
220
221
222
223
# File 'lib/fast_tree/model.rb', line 214

def remove
  # remove subtree
  n_destroyed = self.class.find_subtree_by_root(self).destroy_all

  # fill empty space
  _update_nodes(l_ptr, r_ptr, "r_ptr >= #{r_ptr}", - (width + 1))

  # return count of destroyed nodes
  n_destroyed
end

#root?Boolean

Boolean Methods



244
245
246
# File 'lib/fast_tree/model.rb', line 244

def root?
  self.l_ptr == 0
end

#widthObject



235
236
237
# File 'lib/fast_tree/model.rb', line 235

def width
  r_ptr - l_ptr
end