module ClosureTree::NumericDeterministicOrdering
Public Instance Methods
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 24 def _ct_reorder_children(minimum_sort_order_value = nil) _ct.reorder_with_parent_id(_ct_id, minimum_sort_order_value) end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 12 def _ct_reorder_prior_siblings_if_parent_changed if public_send(:saved_change_to_attribute?, _ct.parent_column_name) && !@was_new_record was_parent_id = public_send(:attribute_before_last_save, _ct.parent_column_name) _ct.reorder_with_parent_id(was_parent_id) end end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 19 def _ct_reorder_siblings(minimum_sort_order_value = nil) _ct.reorder_with_parent_id(_ct_parent_id, minimum_sort_order_value) reload unless destroyed? end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 48 def _ct_sum_order_by(node = nil) stats_sql = <<-SQL.squish SELECT count(*) as total_descendants, max(generations) as max_depth FROM #{_ct.quoted_hierarchy_table_name} SQL stats_sql += " WHERE ancestor_id = #{_ct.quote(node.id)}" if node h = _ct.connection.select_one(stats_sql) depth_column = node ? 'depths.generations' : 'depths.max_depth' node_score = "(1 + anc.#{_ct.quoted_order_column(false)}) * " + "power(#{h['total_descendants']}, #{h['max_depth'].to_i + 1} - #{depth_column})" # We want the NULLs to be first in case we are not ordering roots and they have NULL order. Arel.sql("SUM(#{node_score}) IS NULL DESC, SUM(#{node_score})") end
If node is nil, order the whole tree.
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 113 def add_sibling(sibling, add_after = true) fail "can't add self as sibling" if self == sibling if _ct.dont_order_roots && parent.nil? raise ClosureTree::RootOrderingDisabledError.new("Root ordering is disabled on this model") end # Make sure self isn't dirty, because we're going to call reload: save _ct.with_advisory_lock do prior_sibling_parent = sibling.parent reorder_from_value = if prior_sibling_parent == self.parent [self.order_value, sibling.order_value].compact.min else self.order_value end sibling.order_value = self.order_value sibling.parent = self.parent sibling._ct_skip_sort_order_maintenance! sibling.save # may be a no-op _ct_reorder_siblings(reorder_from_value) # The sort order should be correct now except for self and sibling, which may need to flip: sibling_is_after = self.reload.order_value < sibling.reload.order_value if add_after != sibling_is_after # We need to flip the sort orders: self_ov, sib_ov = self.order_value, sibling.order_value update_order_value(sib_ov) sibling.update_order_value(self_ov) end if prior_sibling_parent != self.parent prior_sibling_parent.try(:_ct_reorder_children) end sibling end end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 89 def append_child(child_node) add_child(child_node) end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 105 def append_sibling(sibling_node) add_sibling(sibling_node, true) end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 93 def prepend_child(child_node) child_node.order_value = -1 child_node.parent = self child_node._ct_skip_sort_order_maintenance! if child_node.save _ct_reorder_children child_node.reload else child_node end end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 109 def prepend_sibling(sibling_node) add_sibling(sibling_node, false) end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 67 def roots_and_descendants_preordered if _ct.dont_order_roots raise ClosureTree::RootOrderingDisabledError.new("Root ordering is disabled on this model") end join_sql = <<-SQL.squish JOIN #{_ct.quoted_hierarchy_table_name} anc_hier ON anc_hier.descendant_id = #{_ct.quoted_table_name}.#{_ct.quoted_id_column_name} JOIN #{_ct.quoted_table_name} anc ON anc.#{_ct.quoted_id_column_name} = anc_hier.ancestor_id JOIN ( SELECT descendant_id, max(generations) AS max_depth FROM #{_ct.quoted_hierarchy_table_name} GROUP BY descendant_id ) #{ _ct.t_alias_keyword } depths ON depths.descendant_id = anc.#{_ct.quoted_id_column_name} SQL joins(join_sql) .group("#{_ct.quoted_table_name}.#{_ct.quoted_id_column_name}") .reorder(_ct_sum_order_by) end
Source
# File lib/closure_tree/numeric_deterministic_ordering.rb, line 28 def self_and_descendants_preordered # TODO: raise NotImplementedError if sort_order is not numeric and not null? join_sql = <<-SQL JOIN #{_ct.quoted_hierarchy_table_name} anc_hier ON anc_hier.descendant_id = #{_ct.quoted_hierarchy_table_name}.descendant_id JOIN #{_ct.quoted_table_name} anc ON anc.#{_ct.quoted_id_column_name} = anc_hier.ancestor_id JOIN #{_ct.quoted_hierarchy_table_name} depths ON depths.ancestor_id = #{_ct.quote(self.id)} AND depths.descendant_id = anc.#{_ct.quoted_id_column_name} SQL self_and_descendants .joins(join_sql) .group("#{_ct.quoted_table_name}.#{_ct.quoted_id_column_name}") .reorder(self.class._ct_sum_order_by(self)) end