Skip to content

Commit

Permalink
update depth_cache_column using math
Browse files Browse the repository at this point in the history
Use math to adjust the depth_cache instead of re-calculating the depth

Goal is to remove regular expression change
  • Loading branch information
kbrock committed Mar 11, 2023
1 parent baed000 commit 76c34f2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
26 changes: 21 additions & 5 deletions lib/ancestry/materialized_path_pg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,33 @@ def update_descendants_with_new_ancestry
ancestry_column = ancestry_base_class.ancestry_column
old_ancestry = self.class.generate_ancestry( path_ids_before_last_save )
new_ancestry = self.class.generate_ancestry( path_ids )
update_clause = [
descendants_clause = [
"#{ancestry_column} = replace(#{ancestry_column}, '#{old_ancestry}', '#{new_ancestry}')"
]

if ancestry_base_class.respond_to?(:depth_cache_column) && respond_to?(ancestry_base_class.depth_cache_column)
depth_cache_column = ancestry_base_class.depth_cache_column.to_s
update_clause << "#{depth_cache_column} = length(regexp_replace(regexp_replace(ancestry, '^#{Regexp.escape(old_ancestry)}', '#{new_ancestry}'), '[^#{ancestry_base_class.ancestry_delimiter}]', '', 'g')) #{ancestry_base_class.ancestry_format == :materialized_path2 ? '-' : '+'} 1"
end
update_descendants_hook(descendants_clause, old_ancestry, new_ancestry)
unscoped_descendants_before_save.update_all descendants_clause.join(', ')

unscoped_descendants_before_save.update_all update_clause.join(', ')
end
end

# TODO: only install this if depth_cache is turned on (use chain_methods?)
def update_descendants_hook(descendants_clause, old_ancestry, new_ancestry)
if ancestry_base_class.respond_to?(:depth_cache_column) && respond_to?(ancestry_base_class.depth_cache_column)
depth_cache_column = ancestry_base_class.depth_cache_column.to_s
depth_change = ancestry_depth_change(old_ancestry, new_ancestry)
if depth_change != 0
descendants_clause << "#{depth_cache_column} = #{depth_cache_column} + #{depth_change}"
end
end
end
end
end

# pulled out to make testing easier
def ancestry_depth_change(old_value, new_value)
parse_ancestry_column(new_value).size - parse_ancestry_column(old_value).size
end
end
end
21 changes: 20 additions & 1 deletion test/concerns/depth_caching_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,23 @@ def test_exception_on_unknown_depth_column
end
end
end
end

def test_ancestry_depth_change
AncestryTestDatabase.with_model do |model|
# this lets us test ancestry_depth_change but leaves model in a strange state
# do not create objects
model.extend(Ancestry::MaterializedPathPg)
{
[[], [1]] => +1,
[[1], []] => -1,
[[1], [2]] => 0,
[[1], [1, 2, 3]] => +2,
[[1, 2, 3], [1]] => -2
}.each do |(before, after), diff|
a_before = model.generate_ancestry(before)
a_after = model.generate_ancestry(after)
assert_equal(diff, model.ancestry_depth_change(a_before, a_after))
end
end
end
end

0 comments on commit 76c34f2

Please sign in to comment.