lib/acts_as_ordered_tree/node.rb
# coding: utf-8
require 'acts_as_ordered_tree/node/attributes'
require 'acts_as_ordered_tree/node/movements'
require 'acts_as_ordered_tree/node/predicates'
require 'acts_as_ordered_tree/node/reloading'
require 'acts_as_ordered_tree/node/siblings'
require 'acts_as_ordered_tree/node/traversals'
module ActsAsOrderedTree
# ActsAsOrderedTree::Node takes care of tree integrity when record is saved
# via usual ActiveRecord mechanism
class Node
include Attributes
include Movements
include Predicates
include Reloading
include Siblings
include Traversals
# @attr_reader [ActiveRecord::Base] original AR record, created, updated or destroyed
attr_reader :record
delegate :id, :parent, :children, :==, :to => :record
def initialize(record)
@record = record
end
# Returns scope to which record should be applied
def scope
if tree.columns.scope?
tree.base_class.where Hash[tree.columns.scope.map { |column| [column, record[column]] }]
else
tree.base_class.where(nil)
end
end
# Convert node to AR::Relation
#
# @return [ActiveRecord::Relation]
def to_relation
scope.where(tree.columns.id => id)
end
# @return [ActsAsOrderedTree::Tree]
def tree
record.class.ordered_tree
end
# Returns node level value (0 for root)
#
# @return [Fixnum]
def level
case
when root? then 0
when depth_column_could_be_used? then depth
when parent_association_loaded? then parent.level + 1
# @todo move it adapters
else ancestors.size
end
end
private
# @return [Arel::Table]
def table
record.class.arel_table
end
def depth_column_could_be_used?
tree.columns.depth? && record.persisted? && !parent_id_changed? && depth?
end
def parent_association_loaded?
record.association(:parent).loaded?
end
end # class Node
end # module ActsAsOrderedTree