deleted_at 0.4.0rc1 → 0.5.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{spec/support/rails/public/favicon.ico → CHANGELOG.md} +0 -0
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +29 -15
- data/lib/deleted_at.rb +29 -29
- data/lib/deleted_at/active_record.rb +37 -0
- data/lib/deleted_at/core.rb +51 -0
- data/lib/deleted_at/{views.rb → legacy.rb} +23 -14
- data/lib/deleted_at/railtie.rb +5 -4
- data/lib/deleted_at/relation.rb +72 -0
- data/lib/deleted_at/table_definition.rb +10 -0
- data/lib/deleted_at/version.rb +1 -1
- metadata +30 -67
- data/.gitignore +0 -78
- data/.rspec +0 -2
- data/.travis.yml +0 -43
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -19
- data/Rakefile +0 -6
- data/deleted_at.gemspec +0 -42
- data/gemfiles/activerecord-4.0.Gemfile +0 -3
- data/gemfiles/activerecord-4.1.Gemfile +0 -3
- data/gemfiles/activerecord-4.2.Gemfile +0 -3
- data/gemfiles/activerecord-5.0.Gemfile +0 -3
- data/gemfiles/activerecord-5.1.Gemfile +0 -3
- data/lib/deleted_at/active_record/base.rb +0 -102
- data/lib/deleted_at/active_record/connection_adapters/abstract/schema_definition.rb +0 -17
- data/lib/deleted_at/active_record/relation.rb +0 -43
- data/spec/deleted_at/active_record/base_spec.rb +0 -21
- data/spec/deleted_at/active_record/relation_spec.rb +0 -166
- data/spec/deleted_at/views_spec.rb +0 -76
- data/spec/spec_helper.rb +0 -28
- data/spec/support/rails/app/models/animals/dog.rb +0 -5
- data/spec/support/rails/app/models/comment.rb +0 -6
- data/spec/support/rails/app/models/post.rb +0 -7
- data/spec/support/rails/app/models/user.rb +0 -7
- data/spec/support/rails/config/database.yml +0 -4
- data/spec/support/rails/config/routes.rb +0 -3
- data/spec/support/rails/db/schema.rb +0 -27
- data/spec/support/rails/log/.gitignore +0 -1
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
require 'deleted_at/views'
|
3
|
-
|
4
|
-
module DeletedAt
|
5
|
-
module ActiveRecord
|
6
|
-
module Base
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
included do
|
10
|
-
class_attribute :archive_with_deleted_at
|
11
|
-
class_attribute :deleted_at_column
|
12
|
-
|
13
|
-
self.archive_with_deleted_at = false
|
14
|
-
end
|
15
|
-
|
16
|
-
module ClassMethods
|
17
|
-
|
18
|
-
def with_deleted_at(options={})
|
19
|
-
|
20
|
-
DeletedAt::ActiveRecord::Base.parse_options(self, options)
|
21
|
-
|
22
|
-
return DeletedAt.logger.warn("You're trying to use `with_deleted_at` on #{name} but you have not installed the views, yet.") unless
|
23
|
-
has_deleted_at_views?
|
24
|
-
|
25
|
-
return DeletedAt.logger.warn("Missing `#{deleted_at_column}` in `#{name}` when trying to employ `deleted_at`") unless
|
26
|
-
has_deleted_at_column?
|
27
|
-
|
28
|
-
# We are confident at this point that the tables and views have been setup.
|
29
|
-
# We need to do a bit of wizardy by setting the table name to the actual table
|
30
|
-
# (at this point: model/all), such that the model has all the information
|
31
|
-
# regarding its structure and intended behavior. (e.g. setting primary key)
|
32
|
-
DeletedAt::Views.while_spoofing_table_name(self, ::DeletedAt::Views.all_table(self)) do
|
33
|
-
reset_primary_key
|
34
|
-
end
|
35
|
-
|
36
|
-
DeletedAt::ActiveRecord::Base.setup_class_views(self)
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def has_deleted_at_column?
|
42
|
-
columns.map(&:name).include?(deleted_at_column)
|
43
|
-
end
|
44
|
-
|
45
|
-
def has_deleted_at_views?
|
46
|
-
::DeletedAt::Views.all_table_exists?(self) && ::DeletedAt::Views.deleted_view_exists?(self)
|
47
|
-
end
|
48
|
-
|
49
|
-
def deleted_at_attributes
|
50
|
-
attributes = {
|
51
|
-
deleted_at_column => Time.now.utc
|
52
|
-
}
|
53
|
-
|
54
|
-
|
55
|
-
attributes
|
56
|
-
end
|
57
|
-
|
58
|
-
end # End ClassMethods
|
59
|
-
|
60
|
-
def destroy
|
61
|
-
if self.archive_with_deleted_at?
|
62
|
-
with_transaction_returning_status do
|
63
|
-
run_callbacks :destroy do
|
64
|
-
update_columns(self.class.deleted_at_attributes)
|
65
|
-
self
|
66
|
-
end
|
67
|
-
end
|
68
|
-
else
|
69
|
-
super
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.remove_class_views(model)
|
74
|
-
model.archive_with_deleted_at = false
|
75
|
-
model.send(:remove_const, :All) if model.const_defined?(:All)
|
76
|
-
model.send(:remove_const, :Deleted) if model.const_defined?(:Deleted)
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.parse_options(model, options)
|
80
|
-
model.deleted_at_column = (options.try(:[], :deleted_at).try(:[], :column) || :deleted_at).to_s
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
def self.setup_class_views(model)
|
85
|
-
model.archive_with_deleted_at = true
|
86
|
-
model.const_set(:All, Class.new(model) do |klass|
|
87
|
-
class_eval <<-AAA
|
88
|
-
self.table_name = '#{::DeletedAt::Views.all_table(klass)}'
|
89
|
-
AAA
|
90
|
-
end)
|
91
|
-
|
92
|
-
model.const_set(:Deleted, Class.new(model) do |klass|
|
93
|
-
class_eval <<-AAA
|
94
|
-
self.table_name = '#{::DeletedAt::Views.deleted_view(klass)}'
|
95
|
-
AAA
|
96
|
-
end)
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module DeletedAt
|
2
|
-
module ActiveRecord
|
3
|
-
module ConnectionAdapters #:nodoc:
|
4
|
-
module TableDefinition
|
5
|
-
|
6
|
-
def timestamps(**options)
|
7
|
-
options[:null] = false if options[:null].nil?
|
8
|
-
|
9
|
-
column(:created_at, :datetime, options)
|
10
|
-
column(:updated_at, :datetime, options)
|
11
|
-
column(:deleted_at, :datetime, options.merge(null: true)) if options[:deleted_at]
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
|
2
|
-
module DeletedAt
|
3
|
-
module ActiveRecord
|
4
|
-
# = Active Record Relation
|
5
|
-
module Relation
|
6
|
-
|
7
|
-
# Deletes the records matching +conditions+ without instantiating the records
|
8
|
-
# first, and hence not calling the +destroy+ method nor invoking callbacks. This
|
9
|
-
# is a single SQL DELETE statement that goes straight to the database, much more
|
10
|
-
# efficient than +destroy_all+. Be careful with relations though, in particular
|
11
|
-
# <tt>:dependent</tt> rules defined on associations are not honored. Returns the
|
12
|
-
# number of rows affected.
|
13
|
-
#
|
14
|
-
# Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
|
15
|
-
# Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
|
16
|
-
# Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
|
17
|
-
#
|
18
|
-
# Both calls delete the affected posts all at once with a single DELETE statement.
|
19
|
-
# If you need to destroy dependent associations or call your <tt>before_*</tt> or
|
20
|
-
# +after_destroy+ callbacks, use the +destroy_all+ method instead.
|
21
|
-
#
|
22
|
-
# If an invalid method is supplied, +delete_all+ raises an ActiveRecord error:
|
23
|
-
#
|
24
|
-
# Post.limit(100).delete_all
|
25
|
-
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit
|
26
|
-
def delete_all(*args)
|
27
|
-
conditions = args.pop
|
28
|
-
if archive_with_deleted_at?
|
29
|
-
if conditions
|
30
|
-
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
|
31
|
-
Passing conditions to delete_all is not supported in DeletedAt
|
32
|
-
To achieve the same use where(conditions).delete_all.
|
33
|
-
MESSAGE
|
34
|
-
end
|
35
|
-
update_all(klass.deleted_at_attributes)
|
36
|
-
else
|
37
|
-
super() # Specifically drop args
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe DeletedAt::ActiveRecord::Base do
|
4
|
-
|
5
|
-
context "model missing deleted_at column" do
|
6
|
-
|
7
|
-
it "fails when trying to install" do
|
8
|
-
expect(DeletedAt.install(Comment)).to eq(false)
|
9
|
-
expect(DeletedAt.uninstall(Comment)).to eq(false)
|
10
|
-
end
|
11
|
-
|
12
|
-
it "warns when using with_deleted_at" do
|
13
|
-
expected_stderr = "Missing `deleted_at` in `Comment` when trying to employ `deleted_at`"
|
14
|
-
allow(Comment).to receive(:has_deleted_at_views?).and_return(true)
|
15
|
-
expect(DeletedAt.logger).to receive(:warn).with(expected_stderr)
|
16
|
-
Comment.with_deleted_at
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
@@ -1,166 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe DeletedAt::ActiveRecord::Relation do
|
4
|
-
|
5
|
-
context "models using deleted_at" do
|
6
|
-
|
7
|
-
it "#destroy should set deleted_at" do
|
8
|
-
DeletedAt.install(User)
|
9
|
-
User.create(name: 'bob')
|
10
|
-
User.create(name: 'john')
|
11
|
-
User.create(name: 'sally')
|
12
|
-
|
13
|
-
User.first.destroy
|
14
|
-
|
15
|
-
expect(User.count).to eq(2)
|
16
|
-
expect(User::All.count).to eq(3)
|
17
|
-
expect(User::Deleted.count).to eq(1)
|
18
|
-
DeletedAt.uninstall(User)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "#delete should set deleted_at" do
|
22
|
-
DeletedAt.install(User)
|
23
|
-
User.create(name: 'bob')
|
24
|
-
User.create(name: 'john')
|
25
|
-
User.create(name: 'sally')
|
26
|
-
|
27
|
-
User.first.delete
|
28
|
-
|
29
|
-
expect(User.count).to eq(2)
|
30
|
-
expect(User::All.count).to eq(3)
|
31
|
-
expect(User::Deleted.count).to eq(1)
|
32
|
-
DeletedAt.uninstall(User)
|
33
|
-
end
|
34
|
-
|
35
|
-
context '#destroy_all' do
|
36
|
-
it "should set deleted_at" do
|
37
|
-
DeletedAt.install(User)
|
38
|
-
User.create(name: 'bob')
|
39
|
-
User.create(name: 'john')
|
40
|
-
User.create(name: 'sally')
|
41
|
-
|
42
|
-
User.all.destroy_all
|
43
|
-
|
44
|
-
expect(User.count).to eq(0)
|
45
|
-
expect(User::All.count).to eq(3)
|
46
|
-
expect(User::Deleted.count).to eq(3)
|
47
|
-
DeletedAt.uninstall(User)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "with conditions should set deleted_at" do
|
51
|
-
DeletedAt.install(User)
|
52
|
-
User.create(name: 'bob')
|
53
|
-
User.create(name: 'john')
|
54
|
-
User.create(name: 'sally')
|
55
|
-
|
56
|
-
User.where(name: 'bob').destroy_all
|
57
|
-
|
58
|
-
expect(User.count).to eq(2)
|
59
|
-
expect(User::All.count).to eq(3)
|
60
|
-
expect(User::Deleted.count).to eq(1)
|
61
|
-
DeletedAt.uninstall(User)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context '#delete_all' do
|
66
|
-
it "should set deleted_at" do
|
67
|
-
DeletedAt.install(Animals::Dog)
|
68
|
-
Animals::Dog.create(name: 'bob')
|
69
|
-
Animals::Dog.create(name: 'john')
|
70
|
-
Animals::Dog.create(name: 'sally')
|
71
|
-
|
72
|
-
# conditions should not matter
|
73
|
-
Animals::Dog.all.delete_all(name: 'bob')
|
74
|
-
|
75
|
-
expect(Animals::Dog.count).to eq(0)
|
76
|
-
expect(Animals::Dog::All.count).to eq(3)
|
77
|
-
expect(Animals::Dog::Deleted.count).to eq(3)
|
78
|
-
DeletedAt.uninstall(Animals::Dog)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "with conditions should set deleted_at" do
|
82
|
-
DeletedAt.install(Animals::Dog)
|
83
|
-
Animals::Dog.create(name: 'bob')
|
84
|
-
Animals::Dog.create(name: 'john')
|
85
|
-
Animals::Dog.create(name: 'sally')
|
86
|
-
|
87
|
-
Animals::Dog.where(name: 'bob').delete_all
|
88
|
-
|
89
|
-
expect(Animals::Dog.count).to eq(2)
|
90
|
-
expect(Animals::Dog::All.count).to eq(3)
|
91
|
-
expect(Animals::Dog::Deleted.count).to eq(1)
|
92
|
-
DeletedAt.uninstall(Animals::Dog)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
context "models not using deleted_at" do
|
99
|
-
|
100
|
-
it "#destroy should actually delete the record" do
|
101
|
-
Comment.create(title: 'Agree')
|
102
|
-
Comment.create(title: 'Disagree')
|
103
|
-
Comment.create(title: 'Defer')
|
104
|
-
|
105
|
-
Comment.first.destroy
|
106
|
-
|
107
|
-
expect(Comment.count).to eq(2)
|
108
|
-
end
|
109
|
-
|
110
|
-
it "#delete should actually delete the record" do
|
111
|
-
Comment.create(title: 'Agree')
|
112
|
-
Comment.create(title: 'Disagree')
|
113
|
-
Comment.create(title: 'Defer')
|
114
|
-
|
115
|
-
Comment.first.delete
|
116
|
-
|
117
|
-
expect(Comment.count).to eq(2)
|
118
|
-
end
|
119
|
-
|
120
|
-
context '#destroy_all' do
|
121
|
-
it "should actually delete records" do
|
122
|
-
Comment.create(title: 'Agree')
|
123
|
-
Comment.create(title: 'Disagree')
|
124
|
-
Comment.create(title: 'Defer')
|
125
|
-
|
126
|
-
Comment.all.destroy_all
|
127
|
-
|
128
|
-
expect(Comment.count).to eq(0)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "with conditions should actually delete records" do
|
132
|
-
Comment.create(title: 'Agree')
|
133
|
-
Comment.create(title: 'Disagree')
|
134
|
-
Comment.create(title: 'Defer')
|
135
|
-
|
136
|
-
Comment.where(title: 'Disagree').destroy_all
|
137
|
-
|
138
|
-
expect(Comment.count).to eq(2)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context '#delete_all' do
|
143
|
-
it "should actually delete records" do
|
144
|
-
Comment.create(title: 'Agree')
|
145
|
-
Comment.create(title: 'Disagree')
|
146
|
-
Comment.create(title: 'Defer')
|
147
|
-
|
148
|
-
Comment.all.delete_all
|
149
|
-
|
150
|
-
expect(Comment.count).to eq(0)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "with conditions should actually delete records" do
|
154
|
-
Comment.create(title: 'Agree')
|
155
|
-
Comment.create(title: 'Disagree')
|
156
|
-
Comment.create(title: 'Defer')
|
157
|
-
|
158
|
-
Comment.where(title: 'Agree').delete_all
|
159
|
-
|
160
|
-
expect(Comment.count).to eq(2)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
end
|
165
|
-
|
166
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe DeletedAt::Views do
|
4
|
-
{
|
5
|
-
User => "simple model",
|
6
|
-
Post => "model with customized table_name",
|
7
|
-
Animals::Dog => "namespaced model"
|
8
|
-
}.each do |model, description|
|
9
|
-
|
10
|
-
plural = model.name.pluralize
|
11
|
-
table_name = model.table_name
|
12
|
-
|
13
|
-
describe "#install for #{description}" do
|
14
|
-
after(:each) do
|
15
|
-
DeletedAt.uninstall(model)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should not raise error' do
|
19
|
-
expect{ DeletedAt.install(model) }.to_not raise_error()
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should rename the models table' do
|
23
|
-
DeletedAt.install(model)
|
24
|
-
expect(ActiveRecord::Base.connection.table_exists?("#{table_name}/all")).to be_truthy
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should have a view for all non-deleted #{plural}" do
|
28
|
-
DeletedAt.install(model)
|
29
|
-
if Gem::Version.new(Rails.version) < Gem::Version.new("5.0")
|
30
|
-
expect(ActiveRecord::Base.connection.table_exists?(table_name)).to be_truthy
|
31
|
-
else
|
32
|
-
expect(ActiveRecord::Base.connection.view_exists?(table_name)).to be_truthy
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should have a view for all deleted #{plural}" do
|
37
|
-
DeletedAt.install(model)
|
38
|
-
if Gem::Version.new(Rails.version) < Gem::Version.new("5.0")
|
39
|
-
expect(ActiveRecord::Base.connection.table_exists?("#{table_name}/deleted")).to be_truthy
|
40
|
-
else
|
41
|
-
expect(ActiveRecord::Base.connection.view_exists?("#{table_name}/deleted")).to be_truthy
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'creates the DeletedAt class extensions' do
|
46
|
-
DeletedAt.install(model)
|
47
|
-
expect(model.const_defined?(:All)).to be_truthy
|
48
|
-
expect(model.const_defined?(:Deleted)).to be_truthy
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'sets the correct table name for modified class' do
|
52
|
-
DeletedAt.install(model)
|
53
|
-
expect(model.table_name).to eql(table_name)
|
54
|
-
expect(model::All.table_name).to eql("#{table_name}/all")
|
55
|
-
expect(model::Deleted.table_name).to eql("#{table_name}/deleted")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "#uninstall for #{description}" do
|
60
|
-
before(:each) do
|
61
|
-
DeletedAt.install(model)
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should not raise error' do
|
65
|
-
expect{ DeletedAt.uninstall(model) }.to_not raise_error()
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'should remove model extensions' do
|
69
|
-
DeletedAt.uninstall(model)
|
70
|
-
expect(model.const_defined?(:All)).to be_falsy
|
71
|
-
expect(model.const_defined?(:Deleted)).to be_falsy
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|