|
|
|
@ -42,75 +42,10 @@ |
|
|
|
|
|
|
|
|
|
module OpenProject::NestedSet::RebuildPatch |
|
|
|
|
def self.included(base) |
|
|
|
|
base.class_eval do |
|
|
|
|
scope :invalid_left_and_rights, -> { |
|
|
|
|
joins("LEFT OUTER JOIN #{quoted_table_name} AS parent ON " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_parent_column_name} = parent.#{primary_key}") |
|
|
|
|
.where("#{quoted_table_name}.#{quoted_left_column_name} IS NULL OR " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_right_column_name} IS NULL OR " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_left_column_name} >= " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_right_column_name} OR " + |
|
|
|
|
"(#{quoted_table_name}.#{quoted_parent_column_name} IS NOT NULL AND " + |
|
|
|
|
"(#{quoted_table_name}.#{quoted_left_column_name} <= parent.#{quoted_left_column_name} OR " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_right_column_name} >= parent.#{quoted_right_column_name}))") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
scope :invalid_duplicates_in_columns, -> { |
|
|
|
|
scope_string = Array(acts_as_nested_set_options[:scope]).map { |c| |
|
|
|
|
"#{quoted_table_name}.#{connection.quote_column_name(c)} = duplicates.#{connection.quote_column_name(c)}" |
|
|
|
|
}.join(' AND ') |
|
|
|
|
|
|
|
|
|
scope_string = scope_string.size > 0 ? scope_string + ' AND ' : '' |
|
|
|
|
|
|
|
|
|
joins("LEFT OUTER JOIN #{quoted_table_name} AS duplicates ON " + |
|
|
|
|
scope_string + |
|
|
|
|
"#{quoted_table_name}.#{primary_key} != duplicates.#{primary_key} AND " + |
|
|
|
|
"(#{quoted_table_name}.#{quoted_left_column_name} = duplicates.#{quoted_left_column_name} OR " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_right_column_name} = duplicates.#{quoted_right_column_name})") |
|
|
|
|
.where("duplicates.#{primary_key} IS NOT NULL") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
scope :invalid_roots, -> { |
|
|
|
|
scope_string = Array(acts_as_nested_set_options[:scope]).map { |c| |
|
|
|
|
"#{quoted_table_name}.#{connection.quote_column_name(c)} = other.#{connection.quote_column_name(c)}" |
|
|
|
|
}.join(' AND ') |
|
|
|
|
|
|
|
|
|
scope_string = scope_string.size > 0 ? scope_string + ' AND ' : '' |
|
|
|
|
|
|
|
|
|
joins("LEFT OUTER JOIN #{quoted_table_name} AS other ON " + |
|
|
|
|
"#{quoted_table_name}.#{primary_key} != other.#{primary_key} AND " + |
|
|
|
|
"#{quoted_table_name}.#{parent_column_name} IS NULL AND " + |
|
|
|
|
"other.#{parent_column_name} IS NULL AND " + |
|
|
|
|
scope_string + |
|
|
|
|
"#{quoted_table_name}.#{quoted_left_column_name} <= other.#{quoted_right_column_name} AND " + |
|
|
|
|
"#{quoted_table_name}.#{quoted_right_column_name} >= other.#{quoted_left_column_name}") |
|
|
|
|
.where("other.#{primary_key} IS NOT NULL") |
|
|
|
|
.order(quoted_left_column_name) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extend(ClassMethods) |
|
|
|
|
end |
|
|
|
|
base.extend(ClassMethods) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
module ClassMethods |
|
|
|
|
def selectively_rebuild_silently! |
|
|
|
|
all_invalid |
|
|
|
|
|
|
|
|
|
invalid_roots, invalid_descendants = all_invalid.partition { |node| node.send(parent_column_name).nil? } |
|
|
|
|
|
|
|
|
|
while invalid_descendants.size > 0 |
|
|
|
|
invalid_descendants_parents = invalid_descendants.map { |node| find(node.send(parent_column_name)) } |
|
|
|
|
|
|
|
|
|
new_invalid_roots, invalid_descendants = invalid_descendants_parents.partition { |node| node.send(parent_column_name).nil? } |
|
|
|
|
|
|
|
|
|
invalid_roots += new_invalid_roots |
|
|
|
|
|
|
|
|
|
invalid_descendants.uniq! |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
rebuild_silently!(invalid_roots.uniq) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
# Rebuilds the left & rights if unset or invalid. Also very useful for converting from acts_as_tree. |
|
|
|
|
# Very similar to original nested_set implementation but uses update_all so that callbacks are not triggered |
|
|
|
|
def rebuild_silently!(roots = nil) |
|
|
|
@ -171,10 +106,5 @@ module OpenProject::NestedSet::RebuildPatch |
|
|
|
|
set_left_and_rights.call(root_node) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def all_invalid |
|
|
|
|
invalid = invalid_roots + invalid_left_and_rights + invalid_duplicates_in_columns |
|
|
|
|
invalid.uniq |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|