diff --git a/README.md b/README.md index 5250bdc..c156797 100644 --- a/README.md +++ b/README.md @@ -404,6 +404,8 @@ end ``` This way, the complete hierarchy including all subclasses will be rebuilt. +If you need to preserve a certain children order to rebuild your tree you can call `rebuild` with the keyword `child_order` and give a regular ordering hash: `rebuild!(child_order: {name: :desc})` + ## Deterministic ordering By default, children will be ordered by your database engine, which may not be what you want. diff --git a/lib/closure_tree/hierarchy_maintenance.rb b/lib/closure_tree/hierarchy_maintenance.rb index 3023b24..acc5671 100644 --- a/lib/closure_tree/hierarchy_maintenance.rb +++ b/lib/closure_tree/hierarchy_maintenance.rb @@ -62,7 +62,7 @@ def _ct_before_destroy true # don't prevent destruction end - def rebuild!(called_by_rebuild = false) + def rebuild!(called_by_rebuild = false, child_order: nil) _ct.with_advisory_lock do delete_hierarchy_references unless (defined? @was_new_record) && @was_new_record hierarchy_class.create!(:ancestor => self, :descendant => self, :generations => 0) @@ -82,7 +82,7 @@ def rebuild!(called_by_rebuild = false) _ct_reorder_siblings if !called_by_rebuild end - children.find_each { |c| c.rebuild!(true) } + children.reorder(child_order).find_each { |c| c.rebuild!(true, child_order: child_order) } _ct_reorder_children if _ct.order_is_numeric? && children.present? end @@ -110,10 +110,10 @@ def delete_hierarchy_references module ClassMethods # Rebuilds the hierarchy table based on the parent_id column in the database. # Note that the hierarchy table will be truncated. - def rebuild! + def rebuild!(child_order: nil) _ct.with_advisory_lock do cleanup! - roots.find_each { |n| n.send(:rebuild!) } # roots just uses the parent_id column, so this is safe. + roots.find_each { |n| n.send(:rebuild!, child_order: child_order) } # roots just uses the parent_id column, so this is safe. end nil end diff --git a/spec/closure_tree/hierarchy_maintenance_spec.rb b/spec/closure_tree/hierarchy_maintenance_spec.rb index a4ad09f..321391b 100644 --- a/spec/closure_tree/hierarchy_maintenance_spec.rb +++ b/spec/closure_tree/hierarchy_maintenance_spec.rb @@ -12,6 +12,15 @@ Metal.rebuild! expect(MetalHierarchy.count).to eq(hierarchy_count) end + + it 'rebuild tree with specific child order' do + parent = Metal.create(value: "Parent") + Metal.create(value: "name3") + Metal.create(value: "name1") + Metal.create(value: "name2") + expect(parent.children).to receive(:reorder).with({value: :desc}).once.and_call_original + parent.rebuild!(child_order: {value: :desc}) + end end describe '.cleanup!' do