destroyed_at 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 28d8c5c555222b4e7e45c3a782e60b7026970c37
4
- data.tar.gz: 7f343f2ec3da1c7baec08b06c2433a29a2ab0fc5
3
+ metadata.gz: 072d8f78b587daebb48a6fa406287342c2e1ee3a
4
+ data.tar.gz: 6e963e35a47e92e114fc14038e2e8cc0734bf4b0
5
5
  SHA512:
6
- metadata.gz: 068490e630e8dd369dc013ffa5e5ac9a44cae31bbd88d4e080b1621154dd85da503783d3bf1fd9bb082dbcff97d1079d98561a6b27760ff2782681fbee7bd22f
7
- data.tar.gz: 9f4f2b3dccba9fa4046039e055ed1726d159dea30f4781aac80ab29e1fceea3570e631a74867e94afbd8808da4767a3eeda772c11041aa4dc01a2c8895b2facc
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", "~> 3.2"
23
- spec.add_development_dependency "minitest", "~> 5"
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 "destroyed_at/version"
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 = current_time_from_proper_timezone
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 = nil
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 { |r| r.restore if r.respond_to? :restore }
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)
@@ -1,3 +1,3 @@
1
1
  module DestroyedAt
2
- VERSION = "0.1.5"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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.all.wont_be_empty
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
- user = User.create(:destroyed_at => DateTime.current)
60
- Profile.create(:destroyed_at => DateTime.current, :user => user)
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
- user = User.create(:destroyed_at => DateTime.current)
75
- Dinner.create(:destroyed_at => DateTime.current, :user => user)
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
- #user = User.create(:destroyed_at => DateTime.current, :fleets => [Fleet.new(:destroyed_at => DateTime.current, :car => Car.new)])
83
- user = User.create(:destroyed_at => DateTime.current)
87
+ timestamp = DateTime.current
88
+ user = User.create(:destroyed_at => timestamp)
84
89
  car = Car.create
85
- fleet = Fleet.create(:destroyed_at => DateTime.current, :car => car)
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.before_save_count.must_equal nil
129
+ user.before_update_count.must_equal nil
124
130
  user.restore
125
- user.before_save_count.must_equal nil
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(nil_attribute: '123')
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.must_equal true
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 Minitest::Spec
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
- before_save :increment_counter
45
+ before_update :increment_callback_counter
46
+ validate :increment_validation_counter
46
47
 
47
- attr_accessor :before_save_count, :nil_attribute
48
+ attr_accessor :before_update_count, :validation_count
48
49
 
49
50
  private
50
51
 
51
- def increment_counter
52
- @counter ||= 0
53
- @counter = @counter + 1
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.1.5
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-09-30 00:00:00.000000000 Z
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: '3.2'
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: '3.2'
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: '5'
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: '5'
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
  - - '>='