Module: CollectiveIdea::Acts::NestedSet::Base::InstanceMethods

Defined in:
lib/nested_set/base.rb

Overview

Any instance method that returns a collection makes use of Rails 2.1’s named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.

category.self_and_descendants.count
category.ancestors.find(:all, :conditions => "name like '%foo%'")

Instance Method Summary collapse

Instance Method Details

#<=>(x) ⇒ Object

order by left column



385
386
387
# File 'lib/nested_set/base.rb', line 385

def <=>(x)
  left <=> x.left
end

#==(comparison_object) ⇒ Object

Redefine to act like active record



390
391
392
393
394
395
# File 'lib/nested_set/base.rb', line 390

def ==(comparison_object)
  comparison_object.equal?(self) ||
    (comparison_object.instance_of?(self.class) &&
      comparison_object.id == id &&
      !comparison_object.new_record?)
end

#ancestorsObject

Returns an array of all parents



413
414
415
# File 'lib/nested_set/base.rb', line 413

def ancestors
  without_self self_and_ancestors
end

#child?Boolean

Returns true is this is a child node

Returns:

  • (Boolean)


380
381
382
# File 'lib/nested_set/base.rb', line 380

def child?
  !parent_id.nil?
end

#descendantsObject

Returns a set of all of its children and nested children



444
445
446
# File 'lib/nested_set/base.rb', line 444

def descendants
  without_self self_and_descendants
end

#is_ancestor_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


456
457
458
# File 'lib/nested_set/base.rb', line 456

def is_ancestor_of?(other)
  self.left < other.left && other.left < self.right && same_scope?(other)
end

#is_descendant_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


448
449
450
# File 'lib/nested_set/base.rb', line 448

def is_descendant_of?(other)
  other.left < self.left && self.left < other.right && same_scope?(other)
end

#is_or_is_ancestor_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


460
461
462
# File 'lib/nested_set/base.rb', line 460

def is_or_is_ancestor_of?(other)
  self.left <= other.left && other.left < self.right && same_scope?(other)
end

#is_or_is_descendant_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


452
453
454
# File 'lib/nested_set/base.rb', line 452

def is_or_is_descendant_of?(other)
  other.left <= self.left && self.left < other.right && same_scope?(other)
end

#leaf?Boolean

Returns:

  • (Boolean)


375
376
377
# File 'lib/nested_set/base.rb', line 375

def leaf?
  !new_record? && right - left == 1
end

#leavesObject

Returns a set of all of its nested children which do not have children



428
429
430
# File 'lib/nested_set/base.rb', line 428

def leaves
  descendants.scoped.where("#{q_right} - #{q_left} = 1")
end

#leftObject

Value of the left column



361
362
363
# File 'lib/nested_set/base.rb', line 361

def left
  self[left_column_name]
end

#left_siblingObject

Find the first sibling to the left



472
473
474
# File 'lib/nested_set/base.rb', line 472

def left_sibling
  siblings.where("#{q_left} < ?", left).reverse_order.first
end

#levelObject

Returns the level of this object in the tree root level is 0



434
435
436
# File 'lib/nested_set/base.rb', line 434

def level
  parent_id.nil? ? 0 : ancestors.count
end

#lock_check(cond = nil) ⇒ Object

Lock rows whose lfts and rgts are to be updated



482
483
484
# File 'lib/nested_set/base.rb', line 482

def lock_check(cond=nil)
  nested_set_scope.select(primary_key_column_name).where(cond).lock
end

#move_leftObject

Shorthand method for finding the left sibling and moving to the left of it.



487
488
489
# File 'lib/nested_set/base.rb', line 487

def move_left
  move_to_left_of left_sibling
end

#move_possible?(target) ⇒ Boolean

Returns:

  • (Boolean)


516
517
518
519
520
521
522
# File 'lib/nested_set/base.rb', line 516

def move_possible?(target)
  self != target && # Can't target self
  same_scope?(target) && # can't be in different scopes
  # !(left..right).include?(target.left..target.right) # this needs tested more
  # detect impossible move
  !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right))
end

#move_rightObject

Shorthand method for finding the right sibling and moving to the right of it.



492
493
494
# File 'lib/nested_set/base.rb', line 492

def move_right
  move_to_right_of right_sibling
end

#move_to_child_of(node) ⇒ Object

Move the node to the child of another node (you can pass id only)



507
508
509
# File 'lib/nested_set/base.rb', line 507

def move_to_child_of(node)
  move_to node, :child
end

#move_to_left_of(node) ⇒ Object

Move the node to the left of another node (you can pass id only)



497
498
499
# File 'lib/nested_set/base.rb', line 497

def move_to_left_of(node)
  move_to node, :left
end

#move_to_right_of(node) ⇒ Object

Move the node to the left of another node (you can pass id only)



502
503
504
# File 'lib/nested_set/base.rb', line 502

def move_to_right_of(node)
  move_to node, :right
end

#move_to_rootObject

Move the node to root nodes



512
513
514
# File 'lib/nested_set/base.rb', line 512

def move_to_root
  move_to nil, :root
end

#parent_idObject

Value of the parent column



356
357
358
# File 'lib/nested_set/base.rb', line 356

def parent_id
  self[parent_column_name]
end

#rightObject

Value of the right column



366
367
368
# File 'lib/nested_set/base.rb', line 366

def right
  self[right_column_name]
end

#right_siblingObject

Find the first sibling to the right



477
478
479
# File 'lib/nested_set/base.rb', line 477

def right_sibling
  siblings.where("#{q_left} > ?", left).first
end

#rootObject

Returns root



398
399
400
# File 'lib/nested_set/base.rb', line 398

def root
  self_and_ancestors.first
end

#root?Boolean

Returns true if this is a root node.

Returns:

  • (Boolean)


371
372
373
# File 'lib/nested_set/base.rb', line 371

def root?
  parent_id.nil?
end

#same_scope?(other) ⇒ Boolean

Check if other model is in the same scope

Returns:

  • (Boolean)


465
466
467
468
469
# File 'lib/nested_set/base.rb', line 465

def same_scope?(other)
  Array(acts_as_nested_set_options[:scope]).all? do |attr|
    self.send(attr) == other.send(attr)
  end
end

#self_and_ancestorsObject

Returns the array of all parents and self



408
409
410
# File 'lib/nested_set/base.rb', line 408

def self_and_ancestors
  nested_set_scope.scoped.where("#{q_left} <= ? AND #{q_right} >= ?", left, right)
end

#self_and_childrenObject

Returns the array of all children and self



403
404
405
# File 'lib/nested_set/base.rb', line 403

def self_and_children
  nested_set_scope.scoped.where("#{q_parent} = ? or id = ?", id, id)
end

#self_and_descendantsObject

Returns a set of itself and all of its nested children



439
440
441
# File 'lib/nested_set/base.rb', line 439

def self_and_descendants
  nested_set_scope.scoped.where("#{q_left} >= ? AND #{q_right} <= ?", left, right)
end

#self_and_siblingsObject

Returns the array of all children of the parent, including self



418
419
420
# File 'lib/nested_set/base.rb', line 418

def self_and_siblings
  nested_set_scope.scoped.where(parent_column_name => parent_id)
end

#siblingsObject

Returns the array of all children of the parent, except self



423
424
425
# File 'lib/nested_set/base.rb', line 423

def siblings
  without_self self_and_siblings
end

#to_textObject



524
525
526
527
528
# File 'lib/nested_set/base.rb', line 524

def to_text
  self.class.map_with_level(self_and_descendants) do |node,level|
    "#{'*'*(level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
  end.join("\n")
end