From 38a918180b708dffda123421d3781b1e84f5225c Mon Sep 17 00:00:00 2001 From: Holger Just Date: Tue, 11 Jan 2022 20:02:38 +0100 Subject: [PATCH] Cleanup more dependent objects on project delete With this patch, we will destroy overridden time entry activities (and all of their children) of a project on project destroy. Previously, those objects would have been orphaned. We now also destroy dependent objects of stored queries for a project on destroy. This will cleanup rows from the habtm join table queries_roles which were orphaned before. --- app/models/project.rb | 4 ++-- ..._delete_orphaned_activities_and_queries_roles.rb | 13 +++++++++++++ test/unit/project_test.rb | 10 ++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20220125182055_delete_orphaned_activities_and_queries_roles.rb diff --git a/app/models/project.rb b/app/models/project.rb index fa910fdfe0..4e15b19c8a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -30,7 +30,7 @@ class Project < ActiveRecord::Base IDENTIFIER_MAX_LENGTH = 100 # Specific overridden Activities - has_many :time_entry_activities + has_many :time_entry_activities, :dependent => :destroy has_many :memberships, :class_name => 'Member', :inverse_of => :project # Memberships of active users only has_many :members, @@ -43,7 +43,7 @@ class Project < ActiveRecord::Base belongs_to :default_version, :class_name => 'Version' belongs_to :default_assigned_to, :class_name => 'Principal' has_many :time_entries, :dependent => :destroy - has_many :queries, :dependent => :delete_all + has_many :queries, :dependent => :destroy has_many :documents, :dependent => :destroy has_many :news, lambda {includes(:author)}, :dependent => :destroy has_many :issue_categories, lambda {order(:name)}, :dependent => :delete_all diff --git a/db/migrate/20220125182055_delete_orphaned_activities_and_queries_roles.rb b/db/migrate/20220125182055_delete_orphaned_activities_and_queries_roles.rb new file mode 100644 index 0000000000..fcc3541acc --- /dev/null +++ b/db/migrate/20220125182055_delete_orphaned_activities_and_queries_roles.rb @@ -0,0 +1,13 @@ +class DeleteOrphanedActivitiesAndQueriesRoles < ActiveRecord::Migration[6.1] + def self.up + TimeEntryActivity.left_outer_joins(:project).where(projects:{id: nil}).where.not(project_id: nil).delete_all + + queries_roles = "#{Query.table_name_prefix}queries_roles#{Query.table_name_suffix}" + queries = Query.table_name + ActiveRecord::Base.connection.execute "DELETE #{queries_roles} FROM #{queries_roles} LEFT OUTER JOIN #{queries} ON #{queries_roles}.query_id = #{queries}.id WHERE #{queries}.id IS NULL" + end + + def self.down + # no-op + end +end diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index 676029a141..cf457a48c8 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -233,6 +233,12 @@ def test_destroy # some boards assert @ecookbook.boards.any? + # generate some dependent objects + overridden_activity = TimeEntryActivity.new({:name => "Project", :project => @ecookbook}) + assert overridden_activity.save! + + query = IssueQuery.generate!(:project => @ecookbook, :visibility => Query::VISIBILITY_ROLES, :roles => Role.where(:id => [1, 3]).to_a) + @ecookbook.destroy # make sure that the project non longer exists assert_raise(ActiveRecord::RecordNotFound) {Project.find(@ecookbook.id)} @@ -240,6 +246,10 @@ def test_destroy assert_not Member.where(:project_id => @ecookbook.id).exists? assert_not Board.where(:project_id => @ecookbook.id).exists? assert_not Issue.where(:project_id => @ecookbook.id).exists? + assert_not Enumeration.where(:project_id => @ecookbook.id).exists? + + assert_not Query.where(:project_id => @ecookbook.id).exists? + assert_nil ActiveRecord::Base.connection.select_value("SELECT 1 FROM queries_roles WHERE query_id = #{query.id}") end def test_destroy_should_destroy_subtasks -- 2.34.0