Skip to content

Commit 9937512

Browse files
committed
Recursive restore with has_many/one through assocs
The query to find deleted has_many or has_one through associations was being generated incorrectly because of specifying the wrong foreign key for the table. This change uses the has_one/has_many model's primary key as the foreign key.
1 parent 09e3a9f commit 9937512

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

lib/paranoia.rb

+7-2
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,12 @@ def restore_associated_records(recovery_window_range = nil)
217217

218218
if association_data.nil? && association.macro.to_s == "has_one"
219219
association_class_name = association.klass.name
220-
association_foreign_key = association.foreign_key
220+
221+
association_foreign_key = if association.options[:through].present?
222+
association.klass.primary_key
223+
else
224+
association.foreign_key
225+
end
221226

222227
if association.type
223228
association_polymorphic_type = association.type
@@ -226,7 +231,7 @@ def restore_associated_records(recovery_window_range = nil)
226231
association_find_conditions = { association_foreign_key => self.id }
227232
end
228233

229-
association_class = association_class_name.constantize
234+
association_class = association.klass
230235
if association_class.paranoid?
231236
association_class.only_deleted.where(association_find_conditions).first
232237
.try!(:restore, recursive: true, :recovery_window_range => recovery_window_range)

test/paranoia_test.rb

+65-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ def setup!
4949
'active_column_model_with_uniqueness_validations' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN',
5050
'paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN, active_column_model_with_has_many_relationship_id INTEGER',
5151
'active_column_model_with_has_many_relationships' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN',
52-
'without_default_scope_models' => 'deleted_at DATETIME'
52+
'without_default_scope_models' => 'deleted_at DATETIME',
53+
'paranoid_has_through_restore_parents' => 'deleted_at DATETIME',
54+
'empty_paranoid_models' => 'deleted_at DATETIME',
55+
'paranoid_has_one_throughs' => 'paranoid_has_through_restore_parent_id INTEGER NOT NULL, empty_paranoid_model_id INTEGER NOT NULL, deleted_at DATETIME',
56+
'paranoid_has_many_throughs' => 'paranoid_has_through_restore_parent_id INTEGER NOT NULL, empty_paranoid_model_id INTEGER NOT NULL, deleted_at DATETIME',
5357
}.each do |table_name, columns_as_sql_string|
5458
ActiveRecord::Base.connection.execute "CREATE TABLE #{table_name} (id INTEGER NOT NULL PRIMARY KEY, #{columns_as_sql_string})"
5559
end
@@ -1055,6 +1059,40 @@ def test_restore_recursive_on_polymorphic_has_one_association
10551059
assert_equal 1, polymorphic.class.count
10561060
end
10571061

1062+
def test_recursive_restore_with_has_through_associations
1063+
parent = ParanoidHasThroughRestoreParent.create
1064+
one = EmptyParanoidModel.create
1065+
ParanoidHasOneThrough.create(
1066+
:paranoid_has_through_restore_parent => parent,
1067+
:empty_paranoid_model => one,
1068+
)
1069+
many = Array.new(3) do
1070+
many = EmptyParanoidModel.create
1071+
ParanoidHasManyThrough.create(
1072+
:paranoid_has_through_restore_parent => parent,
1073+
:empty_paranoid_model => many,
1074+
)
1075+
1076+
many
1077+
end
1078+
1079+
assert_equal true, parent.empty_paranoid_model.present?
1080+
assert_equal 3, parent.empty_paranoid_models.count
1081+
1082+
parent.destroy
1083+
1084+
assert_equal true, parent.empty_paranoid_model.reload.deleted?
1085+
assert_equal 0, parent.empty_paranoid_models.count
1086+
1087+
parent = ParanoidHasThroughRestoreParent.with_deleted.first
1088+
parent.restore(recursive: true)
1089+
1090+
assert_equal false, parent.empty_paranoid_model.deleted?
1091+
assert_equal one, parent.empty_paranoid_model
1092+
assert_equal 3, parent.empty_paranoid_models.count
1093+
assert_equal many, parent.empty_paranoid_models
1094+
end
1095+
10581096
# Ensure that we're checking parent_type when restoring
10591097
def test_missing_restore_recursive_on_polymorphic_has_one_association
10601098
parent = ParentModel.create
@@ -1555,3 +1593,29 @@ class ParanoidBelongsTo < ActiveRecord::Base
15551593
belongs_to :paranoid_has_one
15561594
end
15571595
end
1596+
1597+
class ParanoidHasThroughRestoreParent < ActiveRecord::Base
1598+
acts_as_paranoid
1599+
1600+
has_one :paranoid_has_one_through, dependent: :destroy
1601+
has_one :empty_paranoid_model, through: :paranoid_has_one_through, dependent: :destroy
1602+
1603+
has_many :paranoid_has_many_throughs, dependent: :destroy
1604+
has_many :empty_paranoid_models, through: :paranoid_has_many_throughs, dependent: :destroy
1605+
end
1606+
1607+
class EmptyParanoidModel < ActiveRecord::Base
1608+
acts_as_paranoid
1609+
end
1610+
1611+
class ParanoidHasOneThrough < ActiveRecord::Base
1612+
acts_as_paranoid
1613+
belongs_to :paranoid_has_through_restore_parent
1614+
belongs_to :empty_paranoid_model, dependent: :destroy
1615+
end
1616+
1617+
class ParanoidHasManyThrough < ActiveRecord::Base
1618+
acts_as_paranoid
1619+
belongs_to :paranoid_has_through_restore_parent
1620+
belongs_to :empty_paranoid_model, dependent: :destroy
1621+
end

0 commit comments

Comments
 (0)