Module: Ancestry::ClassMethods
- Defined in:
- lib/ancestry/class_methods.rb
Instance Method Summary collapse
-
#arrange(options = {}) ⇒ Object
Arrangement.
-
#build_ancestry_from_parent_ids!(parent_id = nil, ancestry = nil) ⇒ Object
Build ancestry from parent id’s for migration purposes.
-
#check_ancestry_integrity!(options = {}) ⇒ Object
Integrity checking.
-
#orphan_strategy=(orphan_strategy) ⇒ Object
Orphan strategy writer.
-
#rebuild_depth_cache! ⇒ Object
Rebuild depth cache if it got corrupted or if depth caching was just turned on.
-
#restore_ancestry_integrity! ⇒ Object
Integrity restoration.
-
#scope_depth(depth_options, depth) ⇒ Object
Scope on relative depth options.
-
#to_node(object) ⇒ Object
Fetch tree node if necessary.
Instance Method Details
#arrange(options = {}) ⇒ Object
Arrangement
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/ancestry/class_methods.rb', line 31 def arrange = {} scope = if [:order].nil? self.base_class.ordered_by_ancestry else self.base_class.ordered_by_ancestry_and .delete(:order) end # Get all nodes ordered by ancestry and start sorting them into an empty hash scope.all().inject(ActiveSupport::OrderedHash.new) do |arranged_nodes, node| # Find the insertion point for that node by going through its ancestors node.ancestor_ids.inject(arranged_nodes) do |insertion_point, ancestor_id| insertion_point.each do |parent, children| # Change the insertion point to children if node is a descendant of this parent insertion_point = children if ancestor_id == parent.id end; insertion_point end[node] = ActiveSupport::OrderedHash.new; arranged_nodes end end |
#build_ancestry_from_parent_ids!(parent_id = nil, ancestry = nil) ⇒ Object
Build ancestry from parent id’s for migration purposes
120 121 122 123 124 125 126 127 |
# File 'lib/ancestry/class_methods.rb', line 120 def build_ancestry_from_parent_ids! parent_id = nil, ancestry = nil self.base_class.all(:conditions => {self.base_class.parent_column => parent_id}).each do |node| node.without_ancestry_callbacks do node.update_attribute ancestry_column, ancestry end build_ancestry_from_parent_ids! node.id, if ancestry.nil? then "#{node.id}" else "#{ancestry}/#{node.id}" end end end |
#check_ancestry_integrity!(options = {}) ⇒ Object
Integrity checking
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ancestry/class_methods.rb', line 51 def check_ancestry_integrity! = {} parents = {} exceptions = [] if [:report] == :list # For each node ... self.base_class.all.each do |node| begin # ... check validity of ancestry column if !node.valid? and !node.errors[node.class.ancestry_column].blank? raise Ancestry::AncestryIntegrityException.new "Invalid format for ancestry column of node #{node.id}: #{node.read_attribute node.ancestry_column}." end # ... check that all ancestors exist node.ancestor_ids.each do |ancestor_id| unless exists? ancestor_id raise Ancestry::AncestryIntegrityException.new "Reference to non-existent node in node #{node.id}: #{ancestor_id}." end end # ... check that all node parents are consistent with values observed earlier node.path_ids.zip([nil] + node.path_ids).each do |node_id, parent_id| parents[node_id] = parent_id unless parents.has_key? node_id unless parents[node_id] == parent_id raise Ancestry::AncestryIntegrityException.new "Conflicting parent id found in node #{node.id}: #{parent_id || 'nil'} for node #{node_id} while expecting #{parents[node_id] || 'nil'}" end end rescue Ancestry::AncestryIntegrityException => integrity_exception case [:report] when :list then exceptions << integrity_exception when :echo then puts integrity_exception else raise integrity_exception end end end exceptions if [:report] == :list end |
#orphan_strategy=(orphan_strategy) ⇒ Object
Orphan strategy writer
21 22 23 24 25 26 27 28 |
# File 'lib/ancestry/class_methods.rb', line 21 def orphan_strategy= orphan_strategy # Check value of orphan strategy, only rootify, restrict or destroy is allowed if [:rootify, :restrict, :destroy].include? orphan_strategy class_variable_set :@@orphan_strategy, orphan_strategy else raise Ancestry::AncestryException.new("Invalid orphan strategy, valid ones are :rootify, :restrict and :destroy.") end end |
#rebuild_depth_cache! ⇒ Object
Rebuild depth cache if it got corrupted or if depth caching was just turned on
130 131 132 133 134 135 |
# File 'lib/ancestry/class_methods.rb', line 130 def rebuild_depth_cache! raise Ancestry::AncestryException.new("Cannot rebuild depth cache for model without depth caching.") unless respond_to? :depth_cache_column self.base_class.all.each do |node| node.update_attribute depth_cache_column, node.depth end end |
#restore_ancestry_integrity! ⇒ Object
Integrity restoration
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/ancestry/class_methods.rb', line 86 def restore_ancestry_integrity! parents = {} # For each node ... self.base_class.all.each do |node| # ... set its ancestry to nil if invalid if node.errors[node.class.ancestry_column].blank? node.without_ancestry_callbacks do node.update_attribute node.ancestry_column, nil end end # ... save parent of this node in parents array if it exists parents[node.id] = node.parent_id if exists? node.parent_id # Reset parent id in array to nil if it introduces a cycle parent = parents[node.id] until parent.nil? || parent == node.id parent = parents[parent] end parents[node.id] = nil if parent == node.id end # For each node ... self.base_class.all.each do |node| # ... rebuild ancestry from parents array ancestry, parent = nil, parents[node.id] until parent.nil? ancestry, parent = if ancestry.nil? then parent else "#{parent}/#{ancestry}" end, parents[parent] end node.without_ancestry_callbacks do node.update_attribute node.ancestry_column, ancestry end end end |
#scope_depth(depth_options, depth) ⇒ Object
Scope on relative depth options
9 10 11 12 13 14 15 16 17 18 |
# File 'lib/ancestry/class_methods.rb', line 9 def scope_depth , depth .inject(self.base_class) do |scope, option| scope_name, relative_depth = option if [:before_depth, :to_depth, :at_depth, :from_depth, :after_depth].include? scope_name scope.send scope_name, depth + relative_depth else raise Ancestry::AncestryException.new("Unknown depth option: #{scope_name}.") end end end |
#to_node(object) ⇒ Object
Fetch tree node if necessary
4 5 6 |
# File 'lib/ancestry/class_methods.rb', line 4 def to_node object if object.is_a?(self.base_class) then object else find(object) end end |