@@ -123,6 +123,28 class Issue < ActiveRecord::Base | |||||
123 | end |
|
123 | end | |
124 | end |
|
124 | end | |
125 |
|
125 | |||
|
126 | # AR#Base#destroy would raise and StaleObjectError exception | |||
|
127 | # if the issue was already deleted or updated (non matching lock_version). | |||
|
128 | # This is a problem when bulk deleting issues or deleting a project | |||
|
129 | # (because an issue may already be deleted if its parent was deleted | |||
|
130 | # first). | |||
|
131 | # The issue is reloaded by the nested_set before being deleted so | |||
|
132 | # the lock_version condition should not be an issue but we handle it. | |||
|
133 | def destroy | |||
|
134 | super | |||
|
135 | rescue ActiveRecord::StaleObjectError | |||
|
136 | # Stale or already deleted | |||
|
137 | begin | |||
|
138 | reload | |||
|
139 | rescue ActiveRecord::RecordNotFound | |||
|
140 | # The issue was actually already deleted | |||
|
141 | @destroyed = true | |||
|
142 | return freeze | |||
|
143 | end | |||
|
144 | # The issue was stale, retry to destroy | |||
|
145 | super | |||
|
146 | end | |||
|
147 | ||||
126 | # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields |
|
148 | # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields | |
127 | def available_custom_fields |
|
149 | def available_custom_fields | |
128 | (project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : [] |
|
150 | (project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : [] |
@@ -748,6 +748,30 class IssueTest < ActiveSupport::TestCase | |||||
748 | assert_nil TimeEntry.find_by_issue_id(1) |
|
748 | assert_nil TimeEntry.find_by_issue_id(1) | |
749 | end |
|
749 | end | |
750 |
|
750 | |||
|
751 | def test_destroying_a_deleted_issue_should_not_raise_an_error | |||
|
752 | issue = Issue.find(1) | |||
|
753 | Issue.find(1).destroy | |||
|
754 | ||||
|
755 | assert_nothing_raised do | |||
|
756 | assert_no_difference 'Issue.count' do | |||
|
757 | issue.destroy | |||
|
758 | end | |||
|
759 | assert issue.destroyed? | |||
|
760 | end | |||
|
761 | end | |||
|
762 | ||||
|
763 | def test_destroying_a_stale_issue_should_not_raise_an_error | |||
|
764 | issue = Issue.find(1) | |||
|
765 | Issue.find(1).update_attribute :subject, "Updated" | |||
|
766 | ||||
|
767 | assert_nothing_raised do | |||
|
768 | assert_difference 'Issue.count', -1 do | |||
|
769 | issue.destroy | |||
|
770 | end | |||
|
771 | assert issue.destroyed? | |||
|
772 | end | |||
|
773 | end | |||
|
774 | ||||
751 | def test_blocked |
|
775 | def test_blocked | |
752 | blocked_issue = Issue.find(9) |
|
776 | blocked_issue = Issue.find(9) | |
753 | blocking_issue = Issue.find(10) |
|
777 | blocking_issue = Issue.find(10) |
@@ -176,6 +176,18 class ProjectTest < ActiveSupport::TestCase | |||||
176 | assert_nil Issue.first(:conditions => {:project_id => @ecookbook.id}) |
|
176 | assert_nil Issue.first(:conditions => {:project_id => @ecookbook.id}) | |
177 | end |
|
177 | end | |
178 |
|
178 | |||
|
179 | def test_destroy_should_destroy_subtasks | |||
|
180 | issues = (0..2).to_a.map {Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :subject => 'test')} | |||
|
181 | issues[0].update_attribute :parent_issue_id, issues[1].id | |||
|
182 | issues[2].update_attribute :parent_issue_id, issues[1].id | |||
|
183 | assert_equal 2, issues[1].children.count | |||
|
184 | ||||
|
185 | assert_nothing_raised do | |||
|
186 | Project.find(1).destroy | |||
|
187 | end | |||
|
188 | assert Issue.find_all_by_id(issues.map(&:id)).empty? | |||
|
189 | end | |||
|
190 | ||||
179 | def test_destroying_root_projects_should_clear_data |
|
191 | def test_destroying_root_projects_should_clear_data | |
180 | Project.roots.each do |root| |
|
192 | Project.roots.each do |root| | |
181 | root.destroy |
|
193 | root.destroy |
General Comments 0
You need to be logged in to leave comments.
Login now