diff -r 2ca61e72c995 app/models/project.rb --- a/app/models/project.rb Mon Jul 30 01:32:31 2012 +0000 +++ b/app/models/project.rb Tue Jul 31 00:42:18 2012 -0400 @@ -367,6 +367,25 @@ end set_parent!(p) end + + def nested_set_rebuild(p) + sibs = (p.nil? ? self.class.roots : p.children) + to_be_inserted_before = sibs.detect {|c| c.name.to_s.downcase > name.to_s.downcase } + if to_be_inserted_before + move_to_left_of(to_be_inserted_before) + elsif p.nil? + if sibs.empty? + # move_to_root adds the project in first (ie. left) position + move_to_root + else + move_to_right_of(sibs.last) unless self == sibs.last + end + else + # move_to_child_of adds the project in last (ie.right) position + move_to_child_of(p) + end + Issue.update_versions_from_hierarchy_change(self) + end # Sets the parent of the project # Argument can be either a Project, a String, a Fixnum or nil @@ -384,22 +403,7 @@ true elsif p.nil? || (p.active? && move_possible?(p)) # Insert the project so that target's children or root projects stay alphabetically sorted - sibs = (p.nil? ? self.class.roots : p.children) - to_be_inserted_before = sibs.detect {|c| c.name.to_s.downcase > name.to_s.downcase } - if to_be_inserted_before - move_to_left_of(to_be_inserted_before) - elsif p.nil? - if sibs.empty? - # move_to_root adds the project in first (ie. left) position - move_to_root - else - move_to_right_of(sibs.last) unless self == sibs.last - end - else - # move_to_child_of adds the project in last (ie.right) position - move_to_child_of(p) - end - Issue.update_versions_from_hierarchy_change(self) + nested_set_rebuild(p) true else # Can not move to the given target @@ -660,6 +664,15 @@ p = Project.find(:first, :order => 'created_on DESC') p.nil? ? nil : p.identifier.to_s.succ end + + def save + changed = name_changed? + ret_val = super + if changed + nested_set_rebuild(parent) + end + ret_val + end # Copies and saves the Project instance based on the +project+. # Duplicates the source project's: diff -r 2ca61e72c995 test/unit/project_test.rb --- a/test/unit/project_test.rb Mon Jul 30 01:32:31 2012 +0000 +++ b/test/unit/project_test.rb Tue Jul 31 00:42:18 2012 -0400 @@ -300,8 +300,37 @@ assert_equal 4, parent.children.size assert_equal parent.children.all.sort_by(&:name), parent.children.all end + + # See issue #11508, updating a project does not reorder sibilings alphabetically. + def test_rebuild_should_sort_children_alphabetically_on_update + ProjectCustomField.delete_all + + # Create 4 projects under a parent project. + parent = Project.create!(:name => 'Parent', :identifier => 'parent') + Project.create!(:name => 'Project C', :identifier => 'project-c').move_to_child_of(parent) + Project.create!(:name => 'Project B', :identifier => 'project-b').move_to_child_of(parent) + Project.create!(:name => 'Project D', :identifier => 'project-d').move_to_child_of(parent) + renamed_project = Project.create!(:name => 'Project A', :identifier => 'project-a').move_to_child_of(parent) + # Rebuild them all. + Project.update_all("lft = NULL, rgt = NULL") + Project.rebuild! + # Confirm that everything is as expected. + all_projects = Project.find(:all, :order => 'lft') + assert_equal 'Project D', all_projects.last.name + + # Load and modify project-a, which causes defect #11508 + project = Project.find_by_id(renamed_project.id) + project.name = 'Project E' + assert_equal true, project.save + + # Reload all projects and verify that "Project E" is last. + all_projects = Project.find(:all, :order => 'lft') + assert_equal 'Project E', all_projects.last.name + end + + def test_set_parent_should_update_issue_fixed_version_associations_when_a_fixed_version_is_moved_out_of_the_hierarchy # Parent issue with a hierarchy project's fixed version parent_issue = Issue.find(1)