permanent_records 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'activerecord'
data/README.markdown CHANGED
@@ -54,7 +54,22 @@ And if you had dependent records that were set to be destroyed along with the pa
54
54
  # all the comments are destroyed as well
55
55
  User.find(3).revive
56
56
  # all the comments that were just destroyed are now back in pristine condition
57
+
58
+ # forcing deletion works the same way: fi you hard delete a record, its dependent records will also be hard deleted
57
59
 
60
+ ## Can I use default scopes?
61
+
62
+ In Rails 3, yes.
63
+
64
+ default_scope where(:deleted_at => nil)
65
+
66
+ If you use such a default scope, you will need to simulate the `deleted` scope with a method
67
+
68
+ def self.deleted
69
+ self.unscoped.where('deleted_at IS NOT NULL')
70
+ end
71
+
72
+ Rails 2 provides no practical means of overriding default scopes (aside from using something like `Model.with_exclusive_scope { find(id) }`), so you'll need to implement those yourself if you need them.
58
73
 
59
74
  Patches welcome, forks celebrated.
60
75
 
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ begin
9
9
  gem.description = %Q{Never Lose Data. Rather than deleting rows this sets Record#deleted_at and gives you all the scopes you need to work with your data.}
10
10
  gem.email = "gems@6brand.com"
11
11
  gem.homepage = "http://github.com/JackDanger/permanent_records"
12
- gem.authors = ["Jack Danger Canty"]
12
+ gem.authors = ["Jack Danger Canty", "David Sulc"]
13
13
  end
14
14
  rescue LoadError
15
15
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0
1
+ 2.1.0
@@ -75,42 +75,60 @@ module PermanentRecords
75
75
  end
76
76
 
77
77
  def revive
78
- # Rails 3
79
- if ActiveRecord::VERSION::MAJOR >= 3
78
+ if active_record_3?
80
79
  _run_revive_callbacks do
81
80
  set_deleted_at nil
82
81
  end
83
82
  else
84
83
  run_callbacks :before_revive
84
+ attempt_notifying_observers(:before_revive)
85
85
  set_deleted_at nil
86
86
  run_callbacks :after_revive
87
+ attempt_notifying_observers(:after_revive)
87
88
  end
88
89
  self
89
90
  end
90
-
91
- def set_deleted_at(value)
92
- return self unless is_permanent?
93
- record = self.class.find(id)
94
- record.update_attribute(:deleted_at, value)
95
- @attributes, @attributes_cache = record.attributes, record.attributes
96
- end
97
91
 
98
92
  def destroy(force = nil)
99
- if ActiveRecord::VERSION::MAJOR >= 3
100
- return super() unless is_permanent? && (:force != force)
93
+ if active_record_3?
94
+ unless is_permanent? && (:force != force)
95
+ return permanently_delete_records_after{ super() }
96
+ end
101
97
  end
102
98
  destroy_with_permanent_records force
103
99
  end
100
+
101
+ private
102
+ def set_deleted_at(value)
103
+ return self unless is_permanent?
104
+ record = self.class
105
+ record = record.unscoped if active_record_3?
106
+ record = record.find(id)
107
+ record.deleted_at = value
108
+ begin
109
+ # we call save! instead of update_attribute so an ActiveRecord::RecordInvalid
110
+ # error will be raised if the record isn't valid. (This prevents reviving records that
111
+ # disregard validation constraints,)
112
+ record.save!
113
+ @attributes, @attributes_cache = record.attributes, record.attributes
114
+ rescue Exception => e
115
+ # trigger dependent record destruction (they were revived before this record,
116
+ # which cannot be revived due to validations)
117
+ record.destroy
118
+ raise e
119
+ end
120
+ end
104
121
 
105
122
  def destroy_with_permanent_records(force = nil)
106
- if ActiveRecord::VERSION::MAJOR < 3
107
- return destroy_without_permanent_records unless is_permanent? && (:force != force)
123
+ unless active_record_3?
124
+ unless is_permanent? && (:force != force)
125
+ return permanently_delete_records_after{ destroy_without_permanent_records }
126
+ end
108
127
  end
109
128
  unless deleted? || new_record?
110
129
  set_deleted_at Time.now
111
130
  end
112
- # Rails 3
113
- if ActiveRecord::VERSION::MAJOR >= 3
131
+ if active_record_3?
114
132
  _run_destroy_callbacks do
115
133
  save
116
134
  end
@@ -126,16 +144,29 @@ module PermanentRecords
126
144
  self.class.reflections.select do |name, reflection|
127
145
  'destroy' == reflection.options[:dependent].to_s && reflection.klass.is_permanent?
128
146
  end.each do |name, reflection|
129
-
130
- send(name).find(:all,
131
- :conditions => [
132
- "#{reflection.quoted_table_name}.deleted_at > ?" +
133
- " AND " +
134
- "#{reflection.quoted_table_name}.deleted_at < ?",
135
- deleted_at - 3.seconds,
136
- deleted_at + 3.seconds
137
- ]
138
- ).each do |dependent|
147
+ cardinality = reflection.macro.to_s.gsub('has_', '')
148
+ if cardinality == 'many'
149
+ records = send(name)
150
+ records = records.unscoped if active_record_3?
151
+ records = records.find(:all,
152
+ :conditions => [
153
+ "#{reflection.quoted_table_name}.deleted_at > ?" +
154
+ " AND " +
155
+ "#{reflection.quoted_table_name}.deleted_at < ?",
156
+ deleted_at - 3.seconds,
157
+ deleted_at + 3.seconds
158
+ ]
159
+ )
160
+ elsif cardinality == 'one'
161
+ if active_record_3?
162
+ self.class.unscoped do
163
+ records = [] << send(name)
164
+ end
165
+ else
166
+ records = [] << send(name)
167
+ end
168
+ end
169
+ records.compact.each do |dependent|
139
170
  dependent.revive
140
171
  end
141
172
 
@@ -143,6 +174,71 @@ module PermanentRecords
143
174
  send(name, :reload)
144
175
  end
145
176
  end
177
+
178
+ def attempt_notifying_observers(callback)
179
+ begin
180
+ notify_observers(callback)
181
+ rescue NoMethodError => e
182
+ # do nothing: this model isn't being observed
183
+ end
184
+ end
185
+
186
+ # return the records corresponding to an association with the `:dependent => :destroy` option
187
+ def get_dependent_records
188
+ dependent_records = {}
189
+
190
+ # check which dependent records are to be destroyed
191
+ klass = self.class
192
+ klass.reflections.each do |key, reflection|
193
+ if reflection.options[:dependent] == :destroy
194
+ next unless records = self.send(key) # skip if there are no dependent record instances
195
+ if records.respond_to? :size
196
+ next unless records.size > 0 # skip if there are no dependent record instances
197
+ else
198
+ records = [] << records
199
+ end
200
+ dependent_record = records.first
201
+ next if dependent_record.nil?
202
+ dependent_records[dependent_record.class] = records.map(&:id)
203
+ end
204
+ end
205
+ dependent_records
206
+ end
207
+
208
+ # If we force the destruction of the record, we will need to force the destruction of dependent records if the
209
+ # user specified `:dependent => :destroy` in the model.
210
+ # By default, the call to super/destroy_with_permanent_records (i.e. the &block param) will only soft delete
211
+ # the dependent records; we keep track of the dependent records
212
+ # that have `:dependent => :destroy` and call destroy(force) on them after the call to super
213
+ def permanently_delete_records_after(&block)
214
+ dependent_records = get_dependent_records
215
+ result = block.call
216
+ if result
217
+ permanently_delete_records(dependent_records)
218
+ end
219
+ result
220
+ end
221
+
222
+ # permanently delete the records (i.e. remove from database)
223
+ def permanently_delete_records(dependent_records)
224
+ dependent_records.each do |klass, ids|
225
+ ids.each do |id|
226
+ begin
227
+ record = klass
228
+ record = record.unscoped if active_record_3?
229
+ record = record.find(id)
230
+ rescue ActiveRecord::RecordNotFound
231
+ next # the record has already been deleted, possibly due to another association with `:dependent => :destroy`
232
+ end
233
+ record.deleted_at = nil
234
+ record.destroy(:force)
235
+ end
236
+ end
237
+ end
238
+
239
+ def active_record_3?
240
+ ActiveRecord::VERSION::MAJOR >= 3
241
+ end
146
242
  end
147
243
  end
148
244
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{permanent_records}
8
- s.version = "2.0.0"
8
+ s.version = "2.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Jack Danger Canty"]
12
- s.date = %q{2011-04-10}
11
+ s.authors = ["Jack Danger Canty", "David Sulc"]
12
+ s.date = %q{2011-06-06}
13
13
  s.description = %q{Never Lose Data. Rather than deleting rows this sets Record#deleted_at and gives you all the scopes you need to work with your data.}
14
14
  s.email = %q{gems@6brand.com}
15
15
  s.extra_rdoc_files = [
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
+ "Gemfile",
21
22
  "LICENSE",
22
23
  "MIT-LICENSE",
23
24
  "README.markdown",
@@ -27,37 +28,35 @@ Gem::Specification.new do |s|
27
28
  "install.rb",
28
29
  "lib/permanent_records.rb",
29
30
  "permanent_records.gemspec",
31
+ "test/comment.rb",
30
32
  "test/database.yml",
33
+ "test/difficulty.rb",
31
34
  "test/hole.rb",
32
35
  "test/kitty.rb",
36
+ "test/location.rb",
33
37
  "test/mole.rb",
34
38
  "test/muskrat.rb",
35
39
  "test/permanent_records_test.rb",
36
40
  "test/schema.rb",
37
41
  "test/test_helper.rb",
42
+ "test/unused_model.rb",
38
43
  "uninstall.rb"
39
44
  ]
40
45
  s.homepage = %q{http://github.com/JackDanger/permanent_records}
41
46
  s.require_paths = ["lib"]
42
47
  s.rubygems_version = %q{1.4.2}
43
48
  s.summary = %q{Soft-delete your ActiveRecord records}
44
- s.test_files = [
45
- "test/hole.rb",
46
- "test/kitty.rb",
47
- "test/mole.rb",
48
- "test/muskrat.rb",
49
- "test/permanent_records_test.rb",
50
- "test/schema.rb",
51
- "test/test_helper.rb"
52
- ]
53
49
 
54
50
  if s.respond_to? :specification_version then
55
51
  s.specification_version = 3
56
52
 
57
53
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
58
55
  else
56
+ s.add_dependency(%q<activerecord>, [">= 0"])
59
57
  end
60
58
  else
59
+ s.add_dependency(%q<activerecord>, [">= 0"])
61
60
  end
62
61
  end
63
62
 
data/test/comment.rb ADDED
@@ -0,0 +1,11 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :hole
3
+
4
+ if ActiveRecord::VERSION::MAJOR >= 3
5
+ default_scope where(:deleted_at => nil)
6
+ else
7
+ def self.unscoped
8
+ self
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class Difficulty < ActiveRecord::Base
2
+ belongs_to :hole
3
+
4
+ if ActiveRecord::VERSION::MAJOR >= 3
5
+ default_scope where(:deleted_at => nil)
6
+ else
7
+ def self.unscoped
8
+ self
9
+ end
10
+ end
11
+ end
data/test/hole.rb CHANGED
@@ -3,4 +3,9 @@ class Hole < ActiveRecord::Base
3
3
  has_many :muskrats, :dependent => :destroy
4
4
  # moles are not permanent
5
5
  has_many :moles, :dependent => :destroy
6
+
7
+ has_one :location, :dependent => :destroy
8
+ has_one :unused_model, :dependent => :destroy
9
+ has_one :difficulty, :dependent => :destroy
10
+ has_many :comments, :dependent => :destroy
6
11
  end
data/test/location.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Location < ActiveRecord::Base
2
+ belongs_to :hole
3
+
4
+ validates_uniqueness_of :name, :scope => :deleted_at
5
+ end
@@ -1,6 +1,11 @@
1
+ # note: functionality to deal with default scopes (and the `unscoped` scope) has been added (and will be tested) for Rails 3
2
+ # this default scope functionality is skipped for Rails 2, because Rails 2 provides no functional means of altering the default scope
3
+ # in particular, setting the default scope in Rails 3 to ignore soft deleted records will work properly, whereas in Rails 2, it will
4
+ # lead to a world of pain
5
+
1
6
  require File.expand_path(File.dirname(__FILE__) + "/test_helper")
2
7
 
3
- %w(hole mole muskrat kitty).each do |a|
8
+ %w(hole mole muskrat kitty location comment difficulty unused_model).each do |a|
4
9
  require File.expand_path(File.dirname(__FILE__) + "/" + a)
5
10
  end
6
11
 
@@ -17,7 +22,28 @@ class PermanentRecordsTest < ActiveSupport::TestCase
17
22
  @hole = Hole.create(:number => 14)
18
23
  @hole.muskrats.create(:name => "Active Muskrat")
19
24
  @hole.muskrats.create(:name => "Deleted Muskrat", :deleted_at => 5.days.ago)
25
+ Location.delete_all
26
+ @location = Location.create(:name => "South wall")
27
+ @hole.location = @location
28
+ @hole.save!
20
29
  @mole = @hole.moles.create(:name => "Grabowski")
30
+
31
+ if ActiveRecord::VERSION::MAJOR >= 3
32
+ Difficulty.unscoped.delete_all
33
+ Comment.unscoped.delete_all
34
+ else
35
+ Difficulty.delete_all
36
+ Comment.delete_all
37
+ end
38
+ # test has_one cardinality with model having a default scope
39
+ @hole_with_difficulty = Hole.create(:number => 16)
40
+ @hole_with_difficulty.difficulty = Difficulty.create!(:name => 'Hard')
41
+ @hole_with_difficulty.save!
42
+
43
+ # test has_many cardinality with model having a default scope
44
+ @hole_with_comments = Hole.create(:number => 16)
45
+ @hole_with_comments.comments << Comment.create!(:text => "Beware of the pond.")
46
+ @hole_with_comments.comments << Comment.create!(:text => "Muskrats live here.")
21
47
  end
22
48
 
23
49
  def teardown
@@ -109,7 +135,7 @@ class PermanentRecordsTest < ActiveSupport::TestCase
109
135
  end
110
136
  end
111
137
 
112
- def test_dependent_permanent_records_should_be_marked_as_deleted
138
+ def test_dependent_permanent_records_with_has_many_cardinality_should_be_marked_as_deleted
113
139
  assert @hole.is_permanent?
114
140
  assert @hole.muskrats.first.is_permanent?
115
141
  assert_no_difference "Muskrat.count" do
@@ -118,7 +144,17 @@ class PermanentRecordsTest < ActiveSupport::TestCase
118
144
  assert @hole.muskrats.first.deleted?
119
145
  end
120
146
 
121
- def test_dependent_permanent_records_should_be_revived_when_parent_is_revived
147
+ def test_dependent_permanent_records_with_has_one_cardinality_should_be_marked_as_deleted
148
+ assert @hole.is_permanent?
149
+ assert @hole.location.is_permanent?
150
+ assert_no_difference "Location.count" do
151
+ @hole.destroy
152
+ end
153
+ assert @hole.location.deleted?
154
+ assert Location.find_by_name("South wall").deleted?
155
+ end
156
+
157
+ def test_dependent_permanent_records_with_has_many_cardinality_should_be_revived_when_parent_is_revived
122
158
  assert @hole.is_permanent?
123
159
  @hole.destroy
124
160
  assert @hole.muskrats.find_by_name("Active Muskrat").deleted?
@@ -126,6 +162,49 @@ class PermanentRecordsTest < ActiveSupport::TestCase
126
162
  assert !@hole.muskrats.find_by_name("Active Muskrat").deleted?
127
163
  end
128
164
 
165
+ def test_dependent_permanent_records_with_has_one_cardinality_should_be_revived_when_parent_is_revived
166
+ assert @hole.is_permanent?
167
+ @hole.destroy
168
+ assert Location.find_by_name("South wall").deleted?
169
+ @hole.revive
170
+ assert !Location.find_by_name("South wall").deleted?
171
+ end
172
+
173
+ # see comment at top of file for reasoning behind conditional testing of default scope
174
+ if ActiveRecord::VERSION::MAJOR >= 3
175
+ def test_dependent_permanent_records_with_has_one_cardinality_and_default_scope_should_be_revived_when_parent_is_revived
176
+ assert @hole_with_difficulty.is_permanent?
177
+ assert_difference("Difficulty.count", -1) do
178
+ @hole_with_difficulty.destroy
179
+ end
180
+ assert_nil Difficulty.find_by_name("Hard")
181
+ assert Difficulty.unscoped.find_by_name("Hard").deleted?
182
+ @hole_with_difficulty.revive
183
+ assert_not_nil Difficulty.find_by_name("Hard")
184
+ assert !Difficulty.unscoped.find_by_name("Hard").deleted?
185
+ end
186
+
187
+ def test_dependent_permanent_records_with_has_many_cardinality_and_default_scope_should_be_revived_when_parent_is_revived
188
+ assert @hole_with_comments.is_permanent?
189
+ assert_difference("Comment.count", -2) do
190
+ @hole_with_comments.destroy
191
+ end
192
+ assert_nil Comment.find_by_text("Beware of the pond.")
193
+ assert Comment.unscoped.find_by_text("Beware of the pond.").deleted?
194
+ @hole_with_comments.revive
195
+ assert_not_nil Comment.find_by_text("Beware of the pond.")
196
+ assert !Comment.unscoped.find_by_text("Beware of the pond.").deleted?
197
+ end
198
+ end
199
+
200
+ def test_inexistent_dependent_models_should_not_cause_errors
201
+ hole_with_unused_model = Hole.create!(:number => 1)
202
+ hole_with_unused_model.destroy
203
+ assert_nothing_raised do
204
+ hole_with_unused_model.revive
205
+ end
206
+ end
207
+
129
208
  def test_old_dependent_permanent_records_should_not_be_revived
130
209
  assert @hole.is_permanent?
131
210
  @hole.destroy
@@ -133,4 +212,46 @@ class PermanentRecordsTest < ActiveSupport::TestCase
133
212
  @hole.revive
134
213
  assert @hole.muskrats.find_by_name("Deleted Muskrat").deleted?
135
214
  end
215
+
216
+ def test_validate_records_before_revival
217
+ duplicate_location = Location.new(@location.attributes)
218
+ @location.destroy
219
+ @location.reload
220
+ duplicate_location.save!
221
+ assert_equal duplicate_location.name, @location.name
222
+ assert_no_difference('Location.not_deleted.count') do
223
+ assert_raise (ActiveRecord::RecordInvalid) do
224
+ @location.revive
225
+ end
226
+ end
227
+ end
228
+
229
+ def test_force_deleting_a_record_with_has_one_force_deletes_dependent_records
230
+ hole = Hole.create(:number => 1)
231
+ location = Location.create(:name => "Near the clubhouse")
232
+ hole.location = location
233
+ hole.save!
234
+
235
+ assert_difference(monitor_for('Hole'), -1) do
236
+ assert_difference(monitor_for('Location'), -1) do
237
+ hole.destroy(:force)
238
+ end
239
+ end
240
+ end
241
+
242
+ def test_force_deleting_a_record_with_has_many_force_deletes_dependent_records
243
+ assert_difference(monitor_for('Hole'), -1) do
244
+ assert_difference(monitor_for('Comment'), -2) do
245
+ @hole_with_comments.destroy(:force)
246
+ end
247
+ end
248
+ end
249
+
250
+ def test_force_deletign_with_multiple_associations
251
+ assert_difference(monitor_for('Muskrat'), -2) do
252
+ assert_difference(monitor_for('Mole'), -1) do
253
+ @hole.destroy(:force)
254
+ end
255
+ end
256
+ end
136
257
  end
data/test/schema.rb CHANGED
@@ -19,5 +19,29 @@ ActiveRecord::Schema.define(:version => 1) do
19
19
  t.string :name
20
20
  t.references :hole
21
21
  end
22
+
23
+ create_table :locations, :force => true do |t|
24
+ t.string :name
25
+ t.references :hole
26
+ t.datetime :deleted_at
27
+ end
28
+
29
+ create_table :comments, :force => true do |t|
30
+ t.string :text
31
+ t.references :hole
32
+ t.datetime :deleted_at
33
+ end
34
+
35
+ create_table :difficulties, :force => true do |t|
36
+ t.string :name
37
+ t.references :hole
38
+ t.datetime :deleted_at
39
+ end
40
+
41
+ create_table :unused_models, :force => true do |t|
42
+ t.string :name
43
+ t.references :hole
44
+ t.datetime :deleted_at
45
+ end
22
46
 
23
47
  end
data/test/test_helper.rb CHANGED
@@ -37,4 +37,9 @@ class ActiveSupport::TestCase #:nodoc:
37
37
  self.use_instantiated_fixtures = false
38
38
 
39
39
  # Add more helper methods to be used by all tests here...
40
+ def monitor_for(class_name)
41
+ result = class_name
42
+ result += '.unscoped' if ActiveRecord::VERSION::MAJOR >= 3
43
+ result += '.count'
44
+ end
40
45
  end
@@ -0,0 +1,2 @@
1
+ class UnusedModel < ActiveRecord::Base
2
+ end
metadata CHANGED
@@ -1,24 +1,38 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: permanent_records
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
+ - 1
8
9
  - 0
9
- - 0
10
- version: 2.0.0
10
+ version: 2.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jack Danger Canty
14
+ - David Sulc
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-04-30 00:00:00 -07:00
19
+ date: 2011-06-06 00:00:00 -07:00
19
20
  default_executable:
20
- dependencies: []
21
-
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ type: :runtime
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ requirement: *id001
34
+ prerelease: false
35
+ name: activerecord
22
36
  description: Never Lose Data. Rather than deleting rows this sets Record#deleted_at and gives you all the scopes you need to work with your data.
23
37
  email: gems@6brand.com
24
38
  executables: []
@@ -30,6 +44,7 @@ extra_rdoc_files:
30
44
  - README.markdown
31
45
  files:
32
46
  - .document
47
+ - Gemfile
33
48
  - LICENSE
34
49
  - MIT-LICENSE
35
50
  - README.markdown
@@ -39,14 +54,18 @@ files:
39
54
  - install.rb
40
55
  - lib/permanent_records.rb
41
56
  - permanent_records.gemspec
57
+ - test/comment.rb
42
58
  - test/database.yml
59
+ - test/difficulty.rb
43
60
  - test/hole.rb
44
61
  - test/kitty.rb
62
+ - test/location.rb
45
63
  - test/mole.rb
46
64
  - test/muskrat.rb
47
65
  - test/permanent_records_test.rb
48
66
  - test/schema.rb
49
67
  - test/test_helper.rb
68
+ - test/unused_model.rb
50
69
  - uninstall.rb
51
70
  has_rdoc: true
52
71
  homepage: http://github.com/JackDanger/permanent_records
@@ -82,11 +101,5 @@ rubygems_version: 1.4.2
82
101
  signing_key:
83
102
  specification_version: 3
84
103
  summary: Soft-delete your ActiveRecord records
85
- test_files:
86
- - test/hole.rb
87
- - test/kitty.rb
88
- - test/mole.rb
89
- - test/muskrat.rb
90
- - test/permanent_records_test.rb
91
- - test/schema.rb
92
- - test/test_helper.rb
104
+ test_files: []
105
+