Skip to content

Commit eaa7c81

Browse files
committed
cleanup hierarchies dependant on deleted element instead of clearing the whole table
1 parent c27057c commit eaa7c81

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

lib/closure_tree/hierarchy_maintenance.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,29 @@ module ClassMethods
112112
# Note that the hierarchy table will be truncated.
113113
def rebuild!
114114
_ct.with_advisory_lock do
115-
hierarchy_class.delete_all # not destroy_all -- we just want a simple truncate.
115+
cleanup!
116116
roots.find_each { |n| n.send(:rebuild!) } # roots just uses the parent_id column, so this is safe.
117117
end
118118
nil
119119
end
120+
121+
def cleanup!
122+
ids_to_delete = []
123+
124+
hierarchy_table = hierarchy_class.arel_table
125+
126+
[:descendant_id, :ancestor_id].each do |foreign_key|
127+
arel_join = hierarchy_table.join(arel_table, Arel::Nodes::OuterJoin)
128+
.on(arel_table[primary_key].eq(hierarchy_table[foreign_key]))
129+
.join_sources
130+
131+
where_condition = {}
132+
where_condition[table_name] = {}
133+
where_condition[table_name][primary_key] = nil
134+
135+
hierarchy_class.joins(arel_join).where(where_condition).destroy_all
136+
end
137+
end
120138
end
121139
end
122140
end

spec/db/schema.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,12 @@
137137

138138
add_foreign_key(:metal, :metal, :column => 'parent_id')
139139

140-
create_table "metal_hierarchies", :id => false do |t|
140+
create_table "metal_hierarchies" do |t|
141141
t.integer "ancestor_id", :null => false
142142
t.integer "descendant_id", :null => false
143143
t.integer "generations", :null => false
144144
end
145145

146-
add_foreign_key(:metal_hierarchies, :metal, :column => 'ancestor_id')
147-
add_foreign_key(:metal_hierarchies, :metal, :column => 'descendant_id')
148-
149146
create_table 'menu_items' do |t|
150147
t.string 'name'
151148
t.integer 'parent_id'

spec/hierarchy_maintenance_spec.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,43 @@
1313
expect(MetalHierarchy.count).to eq(hierarchy_count)
1414
end
1515
end
16+
17+
describe '.cleanup!' do
18+
let!(:parent) { Metal.create(:value => "parent metal") }
19+
let!(:child) { Metal.create(:value => "child metal", parent: parent) }
20+
21+
before do
22+
MetalHierarchy.delete_all
23+
Metal.rebuild!
24+
end
25+
26+
context 'when an element is deleted' do
27+
it 'should delete the child hierarchies' do
28+
child.delete
29+
30+
Metal.cleanup!
31+
32+
expect(MetalHierarchy.where(descendant_id: child.id)).to be_empty
33+
expect(MetalHierarchy.where(ancestor_id: child.id)).to be_empty
34+
end
35+
36+
it 'should not delete the parent hierarchies' do
37+
child.delete
38+
Metal.cleanup!
39+
expect(MetalHierarchy.where(ancestor_id: parent.id).size).to eq 1
40+
end
41+
42+
it 'should not delete other hierarchies' do
43+
other_parent = Metal.create(:value => "other parent metal")
44+
other_child = Metal.create(:value => "other child metal", parent: other_parent)
45+
Metal.rebuild!
46+
47+
child.delete
48+
Metal.cleanup!
49+
50+
expect(MetalHierarchy.where(ancestor_id: other_parent.id).size).to eq 2
51+
expect(MetalHierarchy.where(descendant_id: other_child.id).size).to eq 2
52+
end
53+
end
54+
end
1655
end

0 commit comments

Comments
 (0)