Commit a95a67f0 by Rémi Prévost Committed by Ryan Bigg

Add :recursive option on restore to restore associations

Fixes #91
parent d2814b3a
......@@ -16,11 +16,11 @@ module Paranoia
end
alias :deleted :only_deleted
def restore(id)
def restore(id, opts = {})
if id.is_a?(Array)
id.map { |one_id| restore(one_id) }
id.map { |one_id| restore(one_id, opts) }
else
only_deleted.find(id).restore!
only_deleted.find(id).restore!(opts)
end
end
end
......@@ -52,8 +52,13 @@ module Paranoia
delete_or_soft_delete
end
def restore!
run_callbacks(:restore) { update_column paranoia_column, nil }
def restore!(opts = {})
ActiveRecord::Base.transaction do
run_callbacks(:restore) do
update_column paranoia_column, nil
restore_associated_records if opts[:recursive]
end
end
end
def destroyed?
......@@ -78,6 +83,22 @@ module Paranoia
touch(paranoia_column)
end
end
# restore associated records that have been soft deleted when
# we called #destroy
def restore_associated_records
destroyed_associations = self.class.reflect_on_all_associations.select do |association|
association.options[:dependent] == :destroy
end
destroyed_associations.each do |association|
association = send(association.name)
if association.paranoid?
association.only_deleted.each { |record| record.restore(:recursive => true) }
end
end
end
end
class ActiveRecord::Base
......
......@@ -18,6 +18,7 @@ ActiveRecord::Base.connection.execute 'CREATE TABLE employers (id INTEGER NOT NU
ActiveRecord::Base.connection.execute 'CREATE TABLE employees (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
ActiveRecord::Base.connection.execute 'CREATE TABLE jobs (id INTEGER NOT NULL PRIMARY KEY, employer_id INTEGER NOT NULL, employee_id INTEGER NOT NULL, deleted_at DATETIME)'
ActiveRecord::Base.connection.execute 'CREATE TABLE custom_column_models (id INTEGER NOT NULL PRIMARY KEY, destroyed_at DATETIME)'
ActiveRecord::Base.connection.execute 'CREATE TABLE non_paranoid_models (id INTEGER NOT NULL PRIMARY KEY, parent_model_id INTEGER)'
class ParanoiaTest < Test::Unit::TestCase
def test_plain_model_class_is_not_paranoid
......@@ -305,6 +306,34 @@ class ParanoiaTest < Test::Unit::TestCase
refute c.destroyed?
end
def test_restore_with_associations
parent = ParentModel.create
first_child = parent.very_related_models.create
second_child = parent.non_paranoid_models.create
parent.destroy
assert_equal false, parent.deleted_at.nil?
assert_equal false, first_child.reload.deleted_at.nil?
assert_equal true, second_child.destroyed?
parent.restore!
assert_equal true, parent.deleted_at.nil?
assert_equal false, first_child.reload.deleted_at.nil?
assert_equal true, second_child.destroyed?
parent.destroy
parent.restore(:recursive => true)
assert_equal true, parent.deleted_at.nil?
assert_equal true, first_child.reload.deleted_at.nil?
assert_equal true, second_child.destroyed?
parent.destroy
ParentModel.restore(parent.id, :recursive => true)
assert_equal true, parent.reload.deleted_at.nil?
assert_equal true, first_child.reload.deleted_at.nil?
assert_equal true, second_child.destroyed?
end
def test_observers_notified
a = ParanoidModelWithObservers.create
a.destroy
......@@ -366,6 +395,8 @@ end
class ParentModel < ActiveRecord::Base
acts_as_paranoid
has_many :related_models
has_many :very_related_models, :class_name => 'RelatedModel', dependent: :destroy
has_many :non_paranoid_models, dependent: :destroy
end
class RelatedModel < ActiveRecord::Base
......@@ -395,6 +426,9 @@ class CustomColumnModel < ActiveRecord::Base
acts_as_paranoid column: :destroyed_at
end
class NonParanoidModel < ActiveRecord::Base
end
class ParanoidModelWithObservers < ParanoidModel
def observers_notified
@observers_notified ||= []
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment