destroyed_at 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/destroyed_at.gemspec +4 -2
- data/lib/.DS_Store +0 -0
- data/lib/destroyed_at.rb +32 -8
- data/lib/destroyed_at/belongs_to_association.rb +15 -0
- data/lib/destroyed_at/has_many_association.rb +14 -0
- data/lib/destroyed_at/has_one_association.rb +15 -0
- data/lib/destroyed_at/version.rb +1 -1
- data/test/destroyed_at_test.rb +79 -12
- data/test/test_helper.rb +14 -7
- metadata +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 072d8f78b587daebb48a6fa406287342c2e1ee3a
|
4
|
+
data.tar.gz: 6e963e35a47e92e114fc14038e2e8cc0734bf4b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fe52260f693cdd042dc38b26b55c51fbd2b1ee3043c5ef7273154fd78d3b91c54dc84a36a8a70e92498df6a5ec3b1dfd3a0628540cac6c35f66a8aceeb00171
|
7
|
+
data.tar.gz: 10eeacbd7a71381ddd8401d9069f4cc5d3b1a195b0338d4a46b33d780327b2a57041b3af1ced43e1fa193f25c741ed59c0e47c0bff86cc3e5511bba992d96be7
|
data/destroyed_at.gemspec
CHANGED
@@ -17,10 +17,12 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
+
spec.required_ruby_version = '>= 2.0'
|
21
|
+
|
20
22
|
spec.add_development_dependency "bundler", "~> 1.3"
|
21
23
|
spec.add_development_dependency "rake"
|
22
|
-
spec.add_development_dependency "activerecord", "~>
|
23
|
-
spec.add_development_dependency "minitest"
|
24
|
+
spec.add_development_dependency "activerecord", "~> 4.0.0"
|
25
|
+
spec.add_development_dependency "minitest"
|
24
26
|
spec.add_development_dependency "m"
|
25
27
|
spec.add_development_dependency "sqlite3"
|
26
28
|
spec.add_development_dependency "byebug"
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/destroyed_at.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
require
|
1
|
+
require 'destroyed_at/version'
|
2
|
+
require 'destroyed_at/belongs_to_association'
|
3
|
+
require 'destroyed_at/has_many_association'
|
4
|
+
require 'destroyed_at/has_one_association'
|
2
5
|
|
3
6
|
module DestroyedAt
|
4
7
|
def self.included(klass)
|
@@ -10,11 +13,12 @@ module DestroyedAt
|
|
10
13
|
end
|
11
14
|
|
12
15
|
# Set an object's destroyed_at time.
|
13
|
-
def destroy
|
16
|
+
def destroy(timestamp = nil)
|
17
|
+
timestamp ||= current_time_from_proper_timezone
|
18
|
+
raw_write_attribute(:destroyed_at, timestamp)
|
14
19
|
run_callbacks(:destroy) do
|
15
20
|
destroy_associations
|
16
|
-
self.destroyed_at
|
17
|
-
self.save(callbacks: false)
|
21
|
+
self.class.unscoped.where(self.class.primary_key => id).update_all(destroyed_at: timestamp)
|
18
22
|
@destroyed = true
|
19
23
|
end
|
20
24
|
end
|
@@ -23,15 +27,25 @@ module DestroyedAt
|
|
23
27
|
def restore
|
24
28
|
state = nil
|
25
29
|
run_callbacks(:restore) do
|
26
|
-
self.destroyed_at
|
27
|
-
if state = self.save(callbacks: false, validate: false)
|
28
|
-
@destroyed = false
|
30
|
+
if state = (self.class.unscoped.where(self.class.primary_key => id).update_all(destroyed_at: nil) == 1)
|
29
31
|
_restore_associations
|
32
|
+
raw_write_attribute(:destroyed_at, nil)
|
33
|
+
@destroyed = false
|
34
|
+
true
|
30
35
|
end
|
31
36
|
end
|
32
37
|
state
|
33
38
|
end
|
34
39
|
|
40
|
+
def persisted?
|
41
|
+
!new_record? && destroyed_at.present? || super
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete
|
45
|
+
self.destroyed_at = nil
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
35
49
|
private
|
36
50
|
|
37
51
|
def _set_destruction_state
|
@@ -43,10 +57,20 @@ module DestroyedAt
|
|
43
57
|
def _restore_associations
|
44
58
|
reflections.select { |key, value| value.options[:dependent] == :destroy }.keys.each do |key|
|
45
59
|
assoc = association(key)
|
60
|
+
reload_association = false
|
46
61
|
if assoc.options[:through] && assoc.options[:dependent] == :destroy
|
47
62
|
assoc = association(assoc.options[:through])
|
48
63
|
end
|
49
|
-
assoc.association_scope.each
|
64
|
+
assoc.association_scope.each do |r|
|
65
|
+
if r.respond_to?(:restore) && r.destroyed_at == self.destroyed_at
|
66
|
+
r.restore
|
67
|
+
reload_association = true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if reload_association
|
72
|
+
assoc.reload
|
73
|
+
end
|
50
74
|
end
|
51
75
|
end
|
52
76
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DestroyedAt
|
2
|
+
module BelongsToAssociation
|
3
|
+
def handle_dependency
|
4
|
+
if load_target
|
5
|
+
if options[:dependent] == :destroy && target.respond_to?(:destroyed_at)
|
6
|
+
target.destroy(owner.destroyed_at)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Associations::BelongsToAssociation.send(:prepend, DestroyedAt::BelongsToAssociation)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module DestroyedAt
|
2
|
+
module HasManyAssociation
|
3
|
+
def delete_records(records, method)
|
4
|
+
if method == :destroy
|
5
|
+
records.each { |r| r.destroy(owner.destroyed_at) }
|
6
|
+
update_counter(-records.length) unless inverse_updates_counter_cache?
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveRecord::Associations::HasManyAssociation.send(:prepend, DestroyedAt::HasManyAssociation)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DestroyedAt
|
2
|
+
module HasOneAssociation
|
3
|
+
def delete(method = options[:dependent])
|
4
|
+
if load_target
|
5
|
+
if method == :destroy && target.respond_to?(:destroyed_at)
|
6
|
+
target.destroy(owner.destroyed_at)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Associations::HasOneAssociation.send(:prepend, DestroyedAt::HasOneAssociation)
|
data/lib/destroyed_at/version.rb
CHANGED
data/test/destroyed_at_test.rb
CHANGED
@@ -5,7 +5,7 @@ describe 'Destroying AR models' do
|
|
5
5
|
user = User.create
|
6
6
|
user.destroy
|
7
7
|
User.all.must_be_empty
|
8
|
-
User.unscoped.
|
8
|
+
User.unscoped.load.wont_be_empty
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'Destroying a model will set the timestamp it was destroyed at' do
|
@@ -22,6 +22,7 @@ describe 'Destroying AR models' do
|
|
22
22
|
User.all.must_be_empty
|
23
23
|
user.reload
|
24
24
|
user.restore
|
25
|
+
user.destroyed_at.must_be_nil
|
25
26
|
User.all.wont_be_empty
|
26
27
|
end
|
27
28
|
|
@@ -56,9 +57,11 @@ describe 'Destroying AR models' do
|
|
56
57
|
end
|
57
58
|
|
58
59
|
it 'can restore relationships' do
|
59
|
-
|
60
|
-
|
60
|
+
timestamp = DateTime.current
|
61
|
+
user = User.create(:destroyed_at => timestamp)
|
62
|
+
Profile.create(:destroyed_at => timestamp, :user => user)
|
61
63
|
Profile.count.must_equal 0
|
64
|
+
user.reload
|
62
65
|
user.restore
|
63
66
|
Profile.count.must_equal 1
|
64
67
|
end
|
@@ -71,20 +74,23 @@ describe 'Destroying AR models' do
|
|
71
74
|
end
|
72
75
|
|
73
76
|
it 'will respect has many associations' do
|
74
|
-
|
75
|
-
|
77
|
+
timestamp = DateTime.current
|
78
|
+
user = User.create(:destroyed_at => timestamp)
|
79
|
+
Dinner.create(:destroyed_at => timestamp, :user => user)
|
76
80
|
Dinner.count.must_equal 0
|
81
|
+
user.reload
|
77
82
|
user.restore
|
78
83
|
Dinner.count.must_equal 1
|
79
84
|
end
|
80
85
|
|
81
86
|
it 'will respect has many through associations' do
|
82
|
-
|
83
|
-
user = User.create(:destroyed_at =>
|
87
|
+
timestamp = DateTime.current
|
88
|
+
user = User.create(:destroyed_at => timestamp)
|
84
89
|
car = Car.create
|
85
|
-
fleet = Fleet.create(:destroyed_at =>
|
90
|
+
fleet = Fleet.create(:destroyed_at => timestamp, :car => car)
|
86
91
|
user.fleets = [fleet]
|
87
92
|
user.cars.count.must_equal 0
|
93
|
+
user.reload
|
88
94
|
user.restore
|
89
95
|
user.cars.count.must_equal 1
|
90
96
|
end
|
@@ -120,14 +126,75 @@ describe 'Destroying AR models' do
|
|
120
126
|
it 'skips callbacks' do
|
121
127
|
user = User.create
|
122
128
|
user.destroy
|
123
|
-
user.
|
129
|
+
user.before_update_count.must_equal nil
|
124
130
|
user.restore
|
125
|
-
user.
|
131
|
+
user.before_update_count.must_equal nil
|
126
132
|
end
|
127
133
|
|
128
134
|
it 'skips validations on restore' do
|
129
|
-
user = User.create
|
135
|
+
user = User.create
|
136
|
+
user.validation_count.must_equal 1
|
137
|
+
user.destroy
|
138
|
+
user.validation_count.must_equal 1
|
139
|
+
user.restore
|
140
|
+
user.validation_count.must_equal 1
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'stays persisted after destruction' do
|
144
|
+
user = User.create
|
145
|
+
user.destroy
|
146
|
+
user.persisted?.must_equal true
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'does not allow new records with destroyed_at columns present to be marked persisted' do
|
150
|
+
user = User.new(destroyed_at: Time.now)
|
151
|
+
user.persisted?.must_equal false
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'is not persisted after deletion' do
|
155
|
+
user = User.create
|
156
|
+
user.delete
|
157
|
+
user.persisted?.must_equal false
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'can delete destroyed records and they are marked as not persisted' do
|
161
|
+
user = User.create
|
162
|
+
user.destroy
|
163
|
+
user.persisted?.must_equal true
|
164
|
+
user.delete
|
165
|
+
user.persisted?.must_equal false
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'only restores dependencies destroyed with parent with has many' do
|
169
|
+
user = User.create
|
170
|
+
dinner_one = Dinner.create(user: user, destroyed_at: Time.now - 1.day)
|
171
|
+
dinner_two = Dinner.create(user: user)
|
172
|
+
user.destroy
|
173
|
+
user.restore
|
174
|
+
user.dinners.include?(dinner_one).must_equal false
|
175
|
+
user.dinners.include?(dinner_two).must_equal true
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'only restores dependencies destroyed with parent with has one' do
|
179
|
+
user = User.create
|
180
|
+
profile_1 = Profile.create(user: user, destroyed_at: Time.now - 1.day)
|
181
|
+
profile_2 = Profile.create(user: user)
|
130
182
|
user.destroy
|
131
|
-
user.restore
|
183
|
+
user.restore
|
184
|
+
user.profile.must_equal profile_2
|
185
|
+
profile_1.reload
|
186
|
+
profile_1.destroyed_at.wont_equal nil
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'destroys and restores dependencies in a belongs_to relationship' do
|
190
|
+
user = User.create
|
191
|
+
show = Show.create(user: user)
|
192
|
+
show.destroy
|
193
|
+
show.reload
|
194
|
+
user.reload
|
195
|
+
user.destroyed_at.wont_equal nil
|
196
|
+
show.restore
|
197
|
+
user.reload
|
198
|
+
user.destroyed_at.must_equal nil
|
132
199
|
end
|
133
200
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'bundler/setup'
|
2
|
+
require 'active_record'
|
2
3
|
require 'destroyed_at'
|
3
4
|
require 'minitest/autorun'
|
4
|
-
require 'active_record'
|
5
5
|
require 'byebug'
|
6
6
|
require 'timecop'
|
7
7
|
require 'database_cleaner'
|
8
8
|
|
9
|
-
class
|
9
|
+
class MiniTest::Spec
|
10
10
|
class << self
|
11
11
|
alias :context :describe
|
12
12
|
end
|
@@ -42,15 +42,21 @@ class User < ActiveRecord::Base
|
|
42
42
|
has_one :show
|
43
43
|
has_many :fleets
|
44
44
|
has_many :cars, :through => :fleets, :dependent => :destroy
|
45
|
-
|
45
|
+
before_update :increment_callback_counter
|
46
|
+
validate :increment_validation_counter
|
46
47
|
|
47
|
-
attr_accessor :
|
48
|
+
attr_accessor :before_update_count, :validation_count
|
48
49
|
|
49
50
|
private
|
50
51
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
52
|
+
def increment_callback_counter
|
53
|
+
self.before_update_count ||= 0
|
54
|
+
self.before_update_count = self.before_update_count + 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def increment_validation_counter
|
58
|
+
self.validation_count ||= 0
|
59
|
+
self.validation_count = self.validation_count + 1
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
@@ -89,6 +95,7 @@ end
|
|
89
95
|
|
90
96
|
class Show < ActiveRecord::Base
|
91
97
|
include DestroyedAt
|
98
|
+
belongs_to :user, :dependent => :destroy
|
92
99
|
end
|
93
100
|
|
94
101
|
class Fleet < ActiveRecord::Base
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: destroyed_at
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Dupuis Jr.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,28 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 4.0.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 4.0.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: m
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,7 +150,11 @@ files:
|
|
150
150
|
- README.md
|
151
151
|
- Rakefile
|
152
152
|
- destroyed_at.gemspec
|
153
|
+
- lib/.DS_Store
|
153
154
|
- lib/destroyed_at.rb
|
155
|
+
- lib/destroyed_at/belongs_to_association.rb
|
156
|
+
- lib/destroyed_at/has_many_association.rb
|
157
|
+
- lib/destroyed_at/has_one_association.rb
|
154
158
|
- lib/destroyed_at/version.rb
|
155
159
|
- test/destroyed_at_test.rb
|
156
160
|
- test/test_helper.rb
|
@@ -166,7 +170,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
166
170
|
requirements:
|
167
171
|
- - '>='
|
168
172
|
- !ruby/object:Gem::Version
|
169
|
-
version: '0'
|
173
|
+
version: '2.0'
|
170
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
175
|
requirements:
|
172
176
|
- - '>='
|