rails_soft_deletable 0.0.3 → 0.0.4
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.
- data/README.md +7 -7
- data/lib/rails_soft_deletable.rb +46 -22
- data/lib/rails_soft_deletable/version.rb +1 -1
- data/spec/models.rb +75 -0
- data/spec/rails_soft_deletable_spec.rb +253 -0
- data/spec/schema.rb +11 -0
- data/spec/spec_helper.rb +10 -1
- data/spec/support/environment.rb +27 -0
- data/spec/support/timecop.rb +7 -0
- metadata +50 -2
data/README.md
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
# RailsSoftDeletable
|
2
2
|
|
3
|
-
|
3
|
+
This gem provides soft delete behavior to ActiveRecord 3.2.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
7
|
Add this line to your application's Gemfile:
|
8
8
|
|
9
|
-
gem
|
9
|
+
gem "rails_soft_deletable"
|
10
10
|
|
11
11
|
And then execute:
|
12
12
|
|
13
13
|
$ bundle
|
14
14
|
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install rails_soft_deletable
|
18
|
-
|
19
15
|
## Usage
|
20
16
|
|
21
|
-
|
17
|
+
```ruby
|
18
|
+
class Company < ActiveRecord::Base
|
19
|
+
soft_deletable
|
20
|
+
end
|
21
|
+
```
|
22
22
|
|
23
23
|
## Contributing
|
24
24
|
|
data/lib/rails_soft_deletable.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "rails_soft_deletable/version"
|
2
|
+
require "active_record"
|
2
3
|
|
3
4
|
module RailsSoftDeletable
|
4
5
|
def self.included(base)
|
@@ -47,17 +48,34 @@ module RailsSoftDeletable
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
51
|
+
def deleted_at
|
52
|
+
val = super
|
53
|
+
if val.zero? || val.nil?
|
54
|
+
nil
|
55
|
+
else
|
56
|
+
Time.at(val).in_time_zone
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def destroy(destroy_mode = :soft)
|
61
|
+
if destroy_mode == :hard
|
62
|
+
_original_destroy
|
53
63
|
else
|
54
|
-
|
64
|
+
if destroyed?
|
65
|
+
delete_or_soft_delete(true)
|
66
|
+
else
|
67
|
+
run_callbacks(:destroy) { delete_or_soft_delete(true) }
|
68
|
+
end
|
55
69
|
end
|
56
70
|
end
|
57
71
|
|
58
|
-
def delete
|
59
|
-
|
60
|
-
|
72
|
+
def delete(delete_mode = :soft)
|
73
|
+
if delete_mode == :hard
|
74
|
+
_original_delete
|
75
|
+
else
|
76
|
+
return if new_record?
|
77
|
+
delete_or_soft_delete
|
78
|
+
end
|
61
79
|
end
|
62
80
|
|
63
81
|
def restore!
|
@@ -77,16 +95,25 @@ module RailsSoftDeletable
|
|
77
95
|
alias :restore :restore!
|
78
96
|
|
79
97
|
def destroyed?
|
80
|
-
|
81
|
-
|
98
|
+
!!send(soft_deletable_column)
|
99
|
+
end
|
100
|
+
|
101
|
+
def persisted?
|
102
|
+
@_pretend_persistence || super
|
82
103
|
end
|
83
|
-
alias :deleted? :destroyed?
|
84
104
|
|
85
105
|
private
|
86
106
|
|
107
|
+
def _prepare_for_hard_delete(&block)
|
108
|
+
@_pretend_persistence = true
|
109
|
+
self.class.unscoped(&block)
|
110
|
+
ensure
|
111
|
+
@_pretend_persistence = false
|
112
|
+
end
|
113
|
+
|
87
114
|
def delete_or_soft_delete(with_transaction = false)
|
88
115
|
if destroyed?
|
89
|
-
|
116
|
+
_prepare_for_hard_delete { _original_delete }
|
90
117
|
else
|
91
118
|
touch_soft_deletable_column(with_transaction)
|
92
119
|
end
|
@@ -103,7 +130,7 @@ module RailsSoftDeletable
|
|
103
130
|
def touch_column
|
104
131
|
raise ActiveRecordError, "can not touch on a new record object" unless persisted?
|
105
132
|
|
106
|
-
current_time = current_time_from_proper_timezone.
|
133
|
+
current_time = ("%0.6f" % current_time_from_proper_timezone).to_f
|
107
134
|
changes = {}
|
108
135
|
|
109
136
|
changes[soft_deletable_column.to_s] = write_attribute(soft_deletable_column.to_s, current_time)
|
@@ -117,9 +144,13 @@ module RailsSoftDeletable
|
|
117
144
|
end
|
118
145
|
|
119
146
|
class ActiveRecord::Base
|
120
|
-
def self.
|
121
|
-
alias :
|
122
|
-
alias :
|
147
|
+
def self.soft_deletable(options={})
|
148
|
+
alias :_original_destroy :destroy
|
149
|
+
alias :_original_delete :delete
|
150
|
+
|
151
|
+
private :_original_destroy
|
152
|
+
private :_original_delete
|
153
|
+
|
123
154
|
include RailsSoftDeletable
|
124
155
|
class_attribute :soft_deletable_column
|
125
156
|
|
@@ -135,13 +166,6 @@ class ActiveRecord::Base
|
|
135
166
|
self.class.soft_deletable?
|
136
167
|
end
|
137
168
|
|
138
|
-
# Override the persisted method to allow for the paranoia gem.
|
139
|
-
# If a paranoid record is selected, then we only want to check
|
140
|
-
# if it's a new record, not if it is "destroyed".
|
141
|
-
def persisted?
|
142
|
-
soft_deletable? ? !new_record? : super
|
143
|
-
end
|
144
|
-
|
145
169
|
private
|
146
170
|
|
147
171
|
def soft_deletable_column
|
data/spec/models.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require "active_record"
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Models
|
5
|
+
module SoftDeletableCallbacks
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
attr_reader :before_destroy_called
|
9
|
+
attr_reader :around_destroy_called
|
10
|
+
attr_reader :after_destroy_called
|
11
|
+
|
12
|
+
attr_reader :before_restore_called
|
13
|
+
attr_reader :around_restore_called
|
14
|
+
attr_reader :after_restore_called
|
15
|
+
|
16
|
+
before_destroy :call_before_destroy
|
17
|
+
around_destroy :call_around_destroy
|
18
|
+
after_destroy :call_after_destroy
|
19
|
+
|
20
|
+
before_restore :call_before_restore
|
21
|
+
around_restore :call_around_restore
|
22
|
+
after_restore :call_after_restore
|
23
|
+
|
24
|
+
def call_before_destroy
|
25
|
+
@before_destroy_called = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def call_around_destroy
|
29
|
+
yield
|
30
|
+
@around_destroy_called = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def call_after_destroy
|
34
|
+
@after_destroy_called = true
|
35
|
+
end
|
36
|
+
|
37
|
+
def call_before_restore
|
38
|
+
@before_restore_called = true
|
39
|
+
end
|
40
|
+
|
41
|
+
def call_around_restore
|
42
|
+
yield
|
43
|
+
@around_restore_called = true
|
44
|
+
end
|
45
|
+
|
46
|
+
def call_after_restore
|
47
|
+
@after_restore_called = true
|
48
|
+
end
|
49
|
+
|
50
|
+
def reset_callback_flags!
|
51
|
+
@before_destroy_called = nil
|
52
|
+
@around_destroy_called = nil
|
53
|
+
@after_destroy_called = nil
|
54
|
+
|
55
|
+
@before_restore_called = nil
|
56
|
+
@around_restore_called = nil
|
57
|
+
@after_restore_called = nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class DecimalModel< ActiveRecord::Base
|
66
|
+
soft_deletable
|
67
|
+
|
68
|
+
include Spec::Models::SoftDeletableCallbacks
|
69
|
+
end
|
70
|
+
|
71
|
+
class IntegerModel < ActiveRecord::Base
|
72
|
+
soft_deletable
|
73
|
+
|
74
|
+
include Spec::Models::SoftDeletableCallbacks
|
75
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe RailsSoftDeletable do
|
4
|
+
let (:model) { IntegerModel.create! }
|
5
|
+
let (:decimal_model) { DecimalModel.create! }
|
6
|
+
let (:integer_model) { IntegerModel.create! }
|
7
|
+
|
8
|
+
context "#destroy" do
|
9
|
+
it "marks deleted_at column" do
|
10
|
+
Timecop.freeze(Time.now) do
|
11
|
+
decimal_model.destroy
|
12
|
+
integer_model.destroy
|
13
|
+
|
14
|
+
decimal_deleted_at = DecimalModel.connection.select_value("SELECT deleted_at FROM #{DecimalModel.quoted_table_name} WHERE #{DecimalModel.primary_key} = #{decimal_model.id}")
|
15
|
+
integer_deleted_at = IntegerModel.connection.select_value("SELECT deleted_at FROM #{IntegerModel.quoted_table_name} WHERE #{IntegerModel.primary_key} = #{integer_model.id}")
|
16
|
+
|
17
|
+
expect(decimal_deleted_at).to eq(("%0.6f" % Time.now.to_f).to_f)
|
18
|
+
expect(integer_deleted_at.to_i).to eq(Time.now.to_i)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "soft deletes the record" do
|
23
|
+
Timecop.freeze(Time.now) do
|
24
|
+
decimal_model.destroy
|
25
|
+
integer_model.destroy
|
26
|
+
|
27
|
+
expect(decimal_model.deleted_at).to eq(Time.now)
|
28
|
+
expect(integer_model.deleted_at.to_i).to eq(Time.now.to_i)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "does not mark the deleted_at attribute as changed" do
|
33
|
+
model.destroy
|
34
|
+
|
35
|
+
expect(model).to_not be_deleted_at_changed
|
36
|
+
end
|
37
|
+
|
38
|
+
it "marks the record as destroyed" do
|
39
|
+
model.destroy
|
40
|
+
|
41
|
+
expect(model).to be_destroyed
|
42
|
+
end
|
43
|
+
|
44
|
+
it "marks the record as not persisted" do
|
45
|
+
model.destroy
|
46
|
+
|
47
|
+
expect(model).to_not be_persisted
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not freeze the record" do
|
51
|
+
model.destroy
|
52
|
+
|
53
|
+
expect(decimal_model).to_not be_frozen
|
54
|
+
end
|
55
|
+
|
56
|
+
it "performs destroy callbacks" do
|
57
|
+
model.destroy
|
58
|
+
|
59
|
+
expect(model.before_destroy_called).to eq(true)
|
60
|
+
expect(model.around_destroy_called).to eq(true)
|
61
|
+
expect(model.after_destroy_called).to eq(true)
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when record has already been soft deleted" do
|
65
|
+
before do
|
66
|
+
model.destroy
|
67
|
+
model.reset_callback_flags!
|
68
|
+
end
|
69
|
+
|
70
|
+
it "does not perform destroy callbacks" do
|
71
|
+
model.destroy
|
72
|
+
|
73
|
+
expect(model.before_destroy_called).to be_nil
|
74
|
+
expect(model.around_destroy_called).to be_nil
|
75
|
+
expect(model.after_destroy_called).to be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "hard deletes the record from the database" do
|
79
|
+
model.destroy
|
80
|
+
|
81
|
+
count = model.class.connection.select_value("SELECT COUNT(*) FROM #{model.class.quoted_table_name} WHERE #{model.class.primary_key} = #{model.id}")
|
82
|
+
expect(count).to eq(0)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "with hard destroy mode" do
|
87
|
+
it "hard deletes the record from the database" do
|
88
|
+
model.destroy(:hard)
|
89
|
+
|
90
|
+
count = model.class.connection.select_value("SELECT COUNT(*) FROM #{model.class.quoted_table_name} WHERE #{model.class.primary_key} = #{model.id}")
|
91
|
+
expect(count).to eq(0)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "performs destroy callbacks" do
|
95
|
+
model.destroy(:hard)
|
96
|
+
|
97
|
+
expect(model.before_destroy_called).to eq(true)
|
98
|
+
expect(model.around_destroy_called).to eq(true)
|
99
|
+
expect(model.after_destroy_called).to eq(true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "#delete" do
|
105
|
+
it "marks deleted_at column" do
|
106
|
+
Timecop.freeze(Time.now) do
|
107
|
+
decimal_model.delete
|
108
|
+
integer_model.delete
|
109
|
+
|
110
|
+
decimal_deleted_at = DecimalModel.connection.select_value("SELECT deleted_at FROM #{DecimalModel.quoted_table_name} WHERE #{DecimalModel.primary_key} = #{decimal_model.id}")
|
111
|
+
integer_deleted_at = IntegerModel.connection.select_value("SELECT deleted_at FROM #{IntegerModel.quoted_table_name} WHERE #{IntegerModel.primary_key} = #{integer_model.id}")
|
112
|
+
|
113
|
+
expect(decimal_deleted_at).to eq(("%0.6f" % Time.now.to_f).to_f)
|
114
|
+
expect(integer_deleted_at.to_i).to eq(Time.now.to_i)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "soft deletes the record" do
|
119
|
+
Timecop.freeze(Time.now) do
|
120
|
+
decimal_model.delete
|
121
|
+
integer_model.delete
|
122
|
+
|
123
|
+
expect(decimal_model.deleted_at).to eq(Time.now)
|
124
|
+
expect(integer_model.deleted_at.to_i).to eq(Time.now.to_i)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "does not mark the deleted_at attribute as changed" do
|
129
|
+
model.delete
|
130
|
+
|
131
|
+
expect(model).to_not be_deleted_at_changed
|
132
|
+
end
|
133
|
+
|
134
|
+
it "marks the record as destroyed" do
|
135
|
+
model.delete
|
136
|
+
|
137
|
+
expect(model).to be_destroyed
|
138
|
+
end
|
139
|
+
|
140
|
+
it "marks the record as not persisted" do
|
141
|
+
model.delete
|
142
|
+
|
143
|
+
expect(model).to_not be_persisted
|
144
|
+
end
|
145
|
+
|
146
|
+
it "does not freeze the record" do
|
147
|
+
model.delete
|
148
|
+
|
149
|
+
expect(decimal_model).to_not be_frozen
|
150
|
+
end
|
151
|
+
|
152
|
+
it "does not perform destroy callbacks" do
|
153
|
+
model.delete
|
154
|
+
|
155
|
+
expect(model.before_destroy_called).to be_nil
|
156
|
+
expect(model.around_destroy_called).to be_nil
|
157
|
+
expect(model.after_destroy_called).to be_nil
|
158
|
+
end
|
159
|
+
|
160
|
+
context "when record has already been soft deleted" do
|
161
|
+
before do
|
162
|
+
model.delete
|
163
|
+
end
|
164
|
+
|
165
|
+
it "does not perform destroy callbacks" do
|
166
|
+
model.delete
|
167
|
+
|
168
|
+
expect(model.before_destroy_called).to be_nil
|
169
|
+
expect(model.around_destroy_called).to be_nil
|
170
|
+
expect(model.after_destroy_called).to be_nil
|
171
|
+
end
|
172
|
+
|
173
|
+
it "hard deletes the record from the database" do
|
174
|
+
model.delete
|
175
|
+
|
176
|
+
count = model.class.connection.select_value("SELECT COUNT(*) FROM #{model.class.quoted_table_name} WHERE #{model.class.primary_key} = #{model.id}")
|
177
|
+
expect(count).to eq(0)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "with hard delete mode" do
|
182
|
+
it "hard deletes the record from the database" do
|
183
|
+
model.delete(:hard)
|
184
|
+
|
185
|
+
count = model.class.connection.select_value("SELECT COUNT(*) FROM #{model.class.quoted_table_name} WHERE #{model.class.primary_key} = #{model.id}")
|
186
|
+
expect(count).to eq(0)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "performs destroy callbacks" do
|
190
|
+
model.delete(:hard)
|
191
|
+
|
192
|
+
expect(model.before_destroy_called).to be_nil
|
193
|
+
expect(model.around_destroy_called).to be_nil
|
194
|
+
expect(model.after_destroy_called).to be_nil
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context "#restore!" do
|
200
|
+
before do
|
201
|
+
model.destroy
|
202
|
+
model.reset_callback_flags!
|
203
|
+
end
|
204
|
+
|
205
|
+
it "restores the record" do
|
206
|
+
model.restore!
|
207
|
+
|
208
|
+
expect(model).to be_persisted
|
209
|
+
expect(model.deleted_at).to be_nil
|
210
|
+
expect(model).to_not be_deleted_at_changed
|
211
|
+
expect(model).to_not be_destroyed
|
212
|
+
expect(model).to_not be_new_record
|
213
|
+
expect(model).to_not be_frozen
|
214
|
+
end
|
215
|
+
|
216
|
+
it "resets deleted_at in the database" do
|
217
|
+
model.restore!
|
218
|
+
|
219
|
+
model_deleted_at = model.class.connection.select_value("SELECT deleted_at FROM #{model.class.quoted_table_name} WHERE #{model.class.primary_key} = #{model.id}")
|
220
|
+
expect(model_deleted_at).to eq(0)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "performs restore callbacks" do
|
224
|
+
model.restore!
|
225
|
+
|
226
|
+
expect(model.before_restore_called).to eq(true)
|
227
|
+
expect(model.around_restore_called).to eq(true)
|
228
|
+
expect(model.after_restore_called).to eq(true)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "returns true" do
|
232
|
+
expect(model.restore!).to eq(true)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context "#deleted_at" do
|
237
|
+
context "when record has not been soft deleted" do
|
238
|
+
it "returns nil" do
|
239
|
+
expect(model.deleted_at).to be_nil
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context "when record has been soft deleted" do
|
244
|
+
before do
|
245
|
+
model.destroy
|
246
|
+
end
|
247
|
+
|
248
|
+
it "returns a Time object" do
|
249
|
+
expect(model.deleted_at).to be_kind_of(Time)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
ActiveRecord::Schema.define(version: Time.now.strftime("%Y%m%d%H%M%S")) do
|
4
|
+
create_table "decimal_models", force: true do |t|
|
5
|
+
t.decimal "deleted_at", default: 0
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table "integer_models", force: true do |t|
|
9
|
+
t.integer "deleted_at", default: 0
|
10
|
+
end
|
11
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
require "pathname"
|
2
2
|
ROOT_PATH = Pathname.new(__FILE__).join("../..").expand_path
|
3
|
-
$LOAD_PATH.unshift(ROOT_PATH.join("lib"))
|
3
|
+
$LOAD_PATH.unshift(ROOT_PATH.join("lib").to_s)
|
4
|
+
|
5
|
+
require "rails_soft_deletable"
|
6
|
+
|
7
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
8
|
+
# in spec/support/ and its subdirectories.
|
9
|
+
Dir[ROOT_PATH.join("spec/support/**/*.rb")].each { |f| require f }
|
10
|
+
|
11
|
+
# Require all models.
|
12
|
+
require "models"
|
4
13
|
|
5
14
|
RSpec.configure do |config|
|
6
15
|
# Run specs in random order to surface order dependencies. If you find an
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "active_record"
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Support
|
5
|
+
class Environment
|
6
|
+
DATABASE_FILE = ROOT_PATH.join("tmp/test.sqlite3")
|
7
|
+
SCHEMA_FILE = ROOT_PATH.join("spec/schema.rb")
|
8
|
+
|
9
|
+
def self.setup
|
10
|
+
DATABASE_FILE.dirname.mkpath
|
11
|
+
DATABASE_FILE.delete if DATABASE_FILE.exist?
|
12
|
+
|
13
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: DATABASE_FILE.to_s)
|
14
|
+
|
15
|
+
silence_stream(STDOUT) do
|
16
|
+
load(SCHEMA_FILE)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.before(:suite) do
|
25
|
+
Spec::Support::Environment.setup
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_soft_deletable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-11-
|
13
|
+
date: 2013-11-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -92,6 +92,38 @@ dependencies:
|
|
92
92
|
- - ~>
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '1.6'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: timecop
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
95
127
|
description: Soft deletable for ActiveRecord on Rails 3+.
|
96
128
|
email:
|
97
129
|
- quan@listia.com
|
@@ -102,7 +134,12 @@ extra_rdoc_files: []
|
|
102
134
|
files:
|
103
135
|
- lib/rails_soft_deletable/version.rb
|
104
136
|
- lib/rails_soft_deletable.rb
|
137
|
+
- spec/models.rb
|
138
|
+
- spec/rails_soft_deletable_spec.rb
|
139
|
+
- spec/schema.rb
|
105
140
|
- spec/spec_helper.rb
|
141
|
+
- spec/support/environment.rb
|
142
|
+
- spec/support/timecop.rb
|
106
143
|
- LICENSE.txt
|
107
144
|
- Rakefile
|
108
145
|
- README.md
|
@@ -119,12 +156,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
156
|
- - ! '>='
|
120
157
|
- !ruby/object:Gem::Version
|
121
158
|
version: '0'
|
159
|
+
segments:
|
160
|
+
- 0
|
161
|
+
hash: -741598862832616831
|
122
162
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
163
|
none: false
|
124
164
|
requirements:
|
125
165
|
- - ! '>='
|
126
166
|
- !ruby/object:Gem::Version
|
127
167
|
version: '0'
|
168
|
+
segments:
|
169
|
+
- 0
|
170
|
+
hash: -741598862832616831
|
128
171
|
requirements: []
|
129
172
|
rubyforge_project:
|
130
173
|
rubygems_version: 1.8.24
|
@@ -132,4 +175,9 @@ signing_key:
|
|
132
175
|
specification_version: 3
|
133
176
|
summary: Soft deletable for ActiveRecord on Rails 3+
|
134
177
|
test_files:
|
178
|
+
- spec/models.rb
|
179
|
+
- spec/rails_soft_deletable_spec.rb
|
180
|
+
- spec/schema.rb
|
135
181
|
- spec/spec_helper.rb
|
182
|
+
- spec/support/environment.rb
|
183
|
+
- spec/support/timecop.rb
|