activerecord-prunable 0.2.2 → 0.3.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/Gemfile.lock +26 -28
- data/README.md +38 -19
- data/activerecord-prunable.gemspec +1 -1
- data/lib/active_record/prunable.rb +56 -27
- data/lib/activerecord-prunable.rb +3 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97a945f1fcb57b06d59c5153a1e134a91c38c76f
|
4
|
+
data.tar.gz: e32147dd1b243909a3fb972516ff22ff9c291d23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f27076f89b6decfa04c070d7cc6145b6e9c54c7c71a4903d82d6f8f8cc126eb0f5f3334252cc18cef590475acfd8410d2433594d0aa0793f6ed0a86354679a5b
|
7
|
+
data.tar.gz: 6dc95f9b93600595fe7188207d7c9aead81e3acef805fc2d98602bcc32bd5c2fb9e185ef789bccb9312b588d11b5e3709c38bdc65ccebb90d28db0aa3bfe2427
|
data/Gemfile.lock
CHANGED
@@ -8,41 +8,39 @@ PATH
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activemodel (4.2.
|
12
|
-
activesupport (= 4.2.
|
11
|
+
activemodel (4.2.10)
|
12
|
+
activesupport (= 4.2.10)
|
13
13
|
builder (~> 3.1)
|
14
|
-
activerecord (4.2.
|
15
|
-
activemodel (= 4.2.
|
16
|
-
activesupport (= 4.2.
|
14
|
+
activerecord (4.2.10)
|
15
|
+
activemodel (= 4.2.10)
|
16
|
+
activesupport (= 4.2.10)
|
17
17
|
arel (~> 6.0)
|
18
|
-
activesupport (4.2.
|
18
|
+
activesupport (4.2.10)
|
19
19
|
i18n (~> 0.7)
|
20
|
-
json (~> 1.7, >= 1.7.7)
|
21
20
|
minitest (~> 5.1)
|
22
21
|
thread_safe (~> 0.3, >= 0.3.4)
|
23
22
|
tzinfo (~> 1.1)
|
24
|
-
arel (6.0.
|
25
|
-
builder (3.2.
|
26
|
-
byebug (9.0
|
27
|
-
diff-lcs (1.
|
28
|
-
i18n (0.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
rspec-
|
33
|
-
rspec-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
rspec-expectations (3.5.0)
|
23
|
+
arel (6.0.4)
|
24
|
+
builder (3.2.3)
|
25
|
+
byebug (9.1.0)
|
26
|
+
diff-lcs (1.3)
|
27
|
+
i18n (0.8.6)
|
28
|
+
minitest (5.10.3)
|
29
|
+
rspec (3.6.0)
|
30
|
+
rspec-core (~> 3.6.0)
|
31
|
+
rspec-expectations (~> 3.6.0)
|
32
|
+
rspec-mocks (~> 3.6.0)
|
33
|
+
rspec-core (3.6.0)
|
34
|
+
rspec-support (~> 3.6.0)
|
35
|
+
rspec-expectations (3.6.0)
|
38
36
|
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
-
rspec-support (~> 3.
|
40
|
-
rspec-mocks (3.
|
37
|
+
rspec-support (~> 3.6.0)
|
38
|
+
rspec-mocks (3.6.0)
|
41
39
|
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
-
rspec-support (~> 3.
|
43
|
-
rspec-support (3.
|
44
|
-
thread_safe (0.3.
|
45
|
-
tzinfo (1.2.
|
40
|
+
rspec-support (~> 3.6.0)
|
41
|
+
rspec-support (3.6.0)
|
42
|
+
thread_safe (0.3.6)
|
43
|
+
tzinfo (1.2.3)
|
46
44
|
thread_safe (~> 0.1)
|
47
45
|
|
48
46
|
PLATFORMS
|
@@ -54,4 +52,4 @@ DEPENDENCIES
|
|
54
52
|
rspec (~> 3.0)
|
55
53
|
|
56
54
|
BUNDLED WITH
|
57
|
-
1.
|
55
|
+
1.15.4
|
data/README.md
CHANGED
@@ -1,27 +1,31 @@
|
|
1
|
-
[](https://badge.fury.io/rb/activerecord-prunable) [](https://travis-ci.org/dr2m/activerecord-prunable) [](https://codeclimate.com/github/dr2m/activerecord-prunable)
|
2
|
-
|
3
|
-
# Description
|
1
|
+
# Activerecord-prunable [](https://badge.fury.io/rb/activerecord-prunable) [](https://travis-ci.org/dr2m/activerecord-prunable) [](https://codeclimate.com/github/dr2m/activerecord-prunable)
|
4
2
|
|
5
3
|
Convenient removal of obsolete ActiveRecord models.
|
6
4
|
|
7
|
-
|
5
|
+
## Installation
|
8
6
|
|
9
|
-
|
10
|
-
# Gemfile
|
7
|
+
Add this line to your application's Gemfile:
|
11
8
|
|
12
|
-
|
9
|
+
```ruby
|
10
|
+
gem 'activerecord-prunable'
|
13
11
|
```
|
14
12
|
|
15
|
-
|
13
|
+
And then execute:
|
16
14
|
|
17
|
-
|
18
|
-
2. Define the `:prunable` scope that returns models to prune.
|
15
|
+
$ bundle
|
19
16
|
|
20
|
-
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install activerecord-prunable
|
20
|
+
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
1. Include the `Prunable` module in the ActiveRecord model which needs to be pruned.
|
25
|
+
2. Define the `:prunable` scope which returns models to prune.
|
21
26
|
|
22
27
|
```ruby
|
23
28
|
class Notification < ApplicationRecord
|
24
|
-
|
25
29
|
include ActiveRecord::Prunable
|
26
30
|
|
27
31
|
scope :prunable, -> { where("created_at > ?", 1.month.ago) }
|
@@ -29,10 +33,23 @@ gem "activerecord-prunable"
|
|
29
33
|
# You can also set type of removing records (:destroy or :delete).
|
30
34
|
# By default it's :destroy
|
31
35
|
prune_method :delete
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
or use one of the `prune_after`, `prune_created_after`, `prune_updated_after` methods
|
32
40
|
|
41
|
+
```ruby
|
42
|
+
class Notification < ApplicationRecord
|
43
|
+
include ActiveRecord::Prunable
|
44
|
+
|
45
|
+
prune_after 7.days
|
33
46
|
end
|
34
47
|
```
|
35
48
|
|
49
|
+
`prune_after` is an alias for `prune_created_after`
|
50
|
+
`prune_created_after(TTL)` defines `where('created_at < ?', current_time - TTL)` prunable scope
|
51
|
+
`prune_updated_after(TTL)` defines `where('updated_at < ?', current_time - TTL)` prunable scope
|
52
|
+
|
36
53
|
3. Add a `Prunable.prune!` call to a periodic task.
|
37
54
|
|
38
55
|
Example:
|
@@ -43,39 +60,41 @@ gem "activerecord-prunable"
|
|
43
60
|
every(1.day, 'models.prune', at: '04:20', thread: true) { Prunable.prune! }
|
44
61
|
```
|
45
62
|
|
63
|
+
You can also inject current time `Prunable.prune!(current_time: Time.current)`
|
64
|
+
|
46
65
|
# Advanced Usage
|
47
66
|
|
48
|
-
|
67
|
+
__Pruning a single model:__
|
49
68
|
|
50
69
|
```ruby
|
51
70
|
SomeModel.prune!
|
52
71
|
```
|
53
72
|
|
54
|
-
|
73
|
+
__Pruning multiple models:__
|
74
|
+
Note that the `Prunable.prune!` calls `Rails.application.eager_load!`. It can decrease free memory size.
|
55
75
|
|
56
76
|
```ruby
|
57
77
|
Prunable.prune!(SomeModel, AnotherModel)
|
58
78
|
```
|
59
79
|
|
60
|
-
|
80
|
+
__Set default method of pruning (:destroy or :delete):__
|
61
81
|
|
62
82
|
```ruby
|
63
83
|
Prunable.prune!(prune_method: :delete)
|
64
84
|
```
|
65
85
|
|
66
|
-
|
86
|
+
__Call `:prunable` scope with params:__
|
67
87
|
|
68
88
|
```ruby
|
69
89
|
Prunable.prune!(params: [:foo, :bar])
|
70
90
|
```
|
71
91
|
|
72
|
-
|
73
|
-
|
92
|
+
__Getting an array of all the models which include `ActiveRecord::Prunable`:__
|
74
93
|
```ruby
|
75
94
|
Prunable.models
|
76
95
|
```
|
77
96
|
|
78
|
-
|
97
|
+
__Pruning all models which include `ActiveRecord::Prunable`:__
|
79
98
|
|
80
99
|
```ruby
|
81
100
|
Prunable.prune!
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support'
|
2
4
|
require 'active_record'
|
3
5
|
|
@@ -19,68 +21,95 @@ module ActiveRecord
|
|
19
21
|
|
20
22
|
module ClassMethods
|
21
23
|
def prune_method(method)
|
22
|
-
|
24
|
+
unless check_prune_method(method)
|
25
|
+
logger.info "Incorrect prune method #{method} has been ignored for #{self}"
|
26
|
+
return false
|
27
|
+
end
|
23
28
|
|
24
29
|
logger.info "Prune method #{method} has been set for #{self}"
|
25
30
|
class_variable_set(:@@prune_method, method)
|
26
31
|
end
|
27
32
|
|
28
|
-
def
|
33
|
+
def prune_after(duration)
|
34
|
+
prune_created_after(duration)
|
35
|
+
end
|
36
|
+
|
37
|
+
def prune_created_after(duration)
|
38
|
+
class_variable_set(:@@prune_created_after, duration)
|
39
|
+
end
|
40
|
+
|
41
|
+
def prune_updated_after(duration)
|
42
|
+
class_variable_set(:@@prune_updated_after, duration)
|
43
|
+
end
|
44
|
+
|
45
|
+
def prune!(*params, prune_method: nil, current_time: nil)
|
29
46
|
logger.info "Pruning old records of #{self}"
|
30
47
|
return false unless check_scope(*params)
|
31
48
|
|
32
|
-
scope =
|
33
|
-
|
49
|
+
scope = resolve_scope(*params, current_time)
|
50
|
+
destroyed_records = prune_by_method(scope, prune_method)
|
34
51
|
|
35
|
-
if
|
36
|
-
logger.info "#{
|
52
|
+
if destroyed_records > 0
|
53
|
+
logger.info "#{destroyed_records} records have been removed."
|
37
54
|
else
|
38
|
-
logger.info
|
55
|
+
logger.info 'Nothing to prune.'
|
39
56
|
end
|
40
57
|
|
41
|
-
|
58
|
+
destroyed_records
|
42
59
|
end
|
43
60
|
|
44
61
|
private
|
45
62
|
|
46
63
|
def check_scope(*params)
|
47
|
-
|
48
|
-
|
64
|
+
pruning_means_count = [
|
65
|
+
respond_to?(:prunable),
|
66
|
+
class_variable_defined?(:@@prune_created_after),
|
67
|
+
class_variable_defined?(:@@prune_updated_after)
|
68
|
+
].count(true)
|
69
|
+
|
70
|
+
if pruning_means_count.zero?
|
71
|
+
logger.info "The model hasn't got prunable scope or TTL, action is not allowed."
|
49
72
|
return false
|
50
73
|
end
|
51
74
|
|
52
|
-
|
53
|
-
logger.info
|
75
|
+
if pruning_means_count > 1
|
76
|
+
logger.info 'Ambiguity detected, action is not allowed.'
|
54
77
|
return false
|
55
78
|
end
|
56
79
|
|
57
80
|
true
|
58
81
|
end
|
59
82
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
83
|
+
def resolve_scope(*params, current_time)
|
84
|
+
current_time ||= Time.current
|
85
|
+
|
86
|
+
case
|
87
|
+
when respond_to?(:prunable)
|
88
|
+
prunable(*params)
|
89
|
+
when class_variable_defined?(:@@prune_created_after)
|
90
|
+
where('created_at < ?', current_time - class_variable_get(:@@prune_created_after))
|
91
|
+
when class_variable_defined?(:@@prune_updated_after)
|
92
|
+
where('updated_at < ?', current_time - class_variable_get(:@@prune_updated_after))
|
64
93
|
end
|
65
|
-
|
94
|
+
end
|
95
|
+
|
96
|
+
def check_prune_method(method)
|
97
|
+
%i[destroy delete].include?(method)
|
66
98
|
end
|
67
99
|
|
68
100
|
def prune_by_method(scope, prune_method)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
101
|
+
prune_method = if class_variable_defined?(:@@prune_method)
|
102
|
+
class_variable_get(:@@prune_method)
|
103
|
+
else
|
104
|
+
prune_method || :destroy
|
105
|
+
end
|
74
106
|
|
75
107
|
return false unless check_prune_method(prune_method)
|
76
108
|
|
77
109
|
logger.info "Prune method is #{prune_method}"
|
78
110
|
|
79
|
-
if prune_method == :delete
|
80
|
-
|
81
|
-
else
|
82
|
-
scope.destroy_all.size
|
83
|
-
end
|
111
|
+
return scope.delete_all if prune_method == :delete
|
112
|
+
scope.destroy_all.size
|
84
113
|
end
|
85
114
|
end
|
86
115
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record/prunable'
|
2
4
|
|
3
5
|
module Prunable
|
@@ -11,6 +13,7 @@ module Prunable
|
|
11
13
|
|
12
14
|
def prune!(*models, prune_method: nil, params: [])
|
13
15
|
models = self.models if models.empty?
|
16
|
+
|
14
17
|
models.each do |model|
|
15
18
|
model.prune!(*params, prune_method: prune_method)
|
16
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-prunable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dr2m
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -115,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
115
|
version: '0'
|
116
116
|
requirements: []
|
117
117
|
rubyforge_project:
|
118
|
-
rubygems_version: 2.
|
118
|
+
rubygems_version: 2.5.1
|
119
119
|
signing_key:
|
120
120
|
specification_version: 4
|
121
121
|
summary: Convenient removal of obsolete ActiveRecord models.
|