Skip to content

Commit

Permalink
Fix for issue #15 where on restore, all dependent child association r…
Browse files Browse the repository at this point in the history
…ecords restored regardless of deletion date
  • Loading branch information
Mike Walsh committed Sep 29, 2013
1 parent 5a2742f commit f2876b8
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
14 changes: 10 additions & 4 deletions lib/destroyed_at.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def self.included(klass)
def destroy
run_callbacks(:destroy) do
destroy_associations
self.update_attribute(:destroyed_at, current_time_from_proper_timezone)
self.update_attribute(:destroyed_at, _get_destroy_time)
@destroyed = true
end
end
Expand All @@ -22,29 +22,35 @@ def destroy
def restore
state = nil
run_callbacks(:restore) do
destroyed_time = self.destroyed_at
if state = self.update_attribute(:destroyed_at, nil)
@destroyed = false
_restore_associations
_restore_associations destroyed_time
end
end
state
end

private

def _get_destroy_time
@@destroy_time ||= current_time_from_proper_timezone
end

def _set_destruction_state
@@destroy_time = nil
@destroyed = destroyed_at.present? if has_attribute?(:destroyed_at)
# Don't stop the other callbacks from running
true
end

def _restore_associations
def _restore_associations(destroyed_time)
reflections.select { |key, value| value.options[:dependent] == :destroy }.keys.each do |key|
assoc = association(key)
if assoc.options[:through] && assoc.options[:dependent] == :destroy
assoc = association(assoc.options[:through])
end
assoc.association_scope.each { |r| r.restore if r.respond_to? :restore }
assoc.association_scope.each { |r| r.restore if r.respond_to?(:restore) && (r.destroyed_at.to_i == destroyed_time.to_i) }
end
end
end
26 changes: 26 additions & 0 deletions test/destroyed_at_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,30 @@
User.unscoped.first.restore
Dinner.count.must_equal 3
end

it 'should have the same destroy time for all dependent records' do
user = User.create
5.times do
Dinner.create user: user
end
Dinner.before_destroy do
sleep 1
end
user.destroy
Dinner.unscoped.where(destroyed_at: user.destroyed_at).count.must_equal 5
end

it 'only restores records destroyed at the same time' do
user = User.create
5.times do
Dinner.create user: user
end
Dinner.first.destroy
Dinner.count.must_equal 4
sleep 1
user.destroy
Dinner.count.must_equal 0
user.restore
Dinner.count.must_equal 4
end
end

0 comments on commit f2876b8

Please sign in to comment.