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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c50d3e6673eb120db96d247c7d868fc3c5d33f8
4
- data.tar.gz: 9eb272a6c3208b92cbc3fe434e73b7b4172c493e
3
+ metadata.gz: 97a945f1fcb57b06d59c5153a1e134a91c38c76f
4
+ data.tar.gz: e32147dd1b243909a3fb972516ff22ff9c291d23
5
5
  SHA512:
6
- metadata.gz: ec970da67f57befaa9fe22bd85cc67dc2a6cdc72d92dc1867f7a84d018210acc9f551dbba83891d4fb7e6590ba25f47cd7e0e5d4112db514a16fde872e6a9c68
7
- data.tar.gz: 5d16df66278b8faabab8c6af9a960647e32b2d5834ac811147c777112771e2a8a561b0fd2ff7ff9ee591e938d5de83a10b49904198984d0a4312008d60efa8ce
6
+ metadata.gz: f27076f89b6decfa04c070d7cc6145b6e9c54c7c71a4903d82d6f8f8cc126eb0f5f3334252cc18cef590475acfd8410d2433594d0aa0793f6ed0a86354679a5b
7
+ data.tar.gz: 6dc95f9b93600595fe7188207d7c9aead81e3acef805fc2d98602bcc32bd5c2fb9e185ef789bccb9312b588d11b5e3709c38bdc65ccebb90d28db0aa3bfe2427
@@ -8,41 +8,39 @@ PATH
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (4.2.7.1)
12
- activesupport (= 4.2.7.1)
11
+ activemodel (4.2.10)
12
+ activesupport (= 4.2.10)
13
13
  builder (~> 3.1)
14
- activerecord (4.2.7.1)
15
- activemodel (= 4.2.7.1)
16
- activesupport (= 4.2.7.1)
14
+ activerecord (4.2.10)
15
+ activemodel (= 4.2.10)
16
+ activesupport (= 4.2.10)
17
17
  arel (~> 6.0)
18
- activesupport (4.2.7.1)
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.3)
25
- builder (3.2.2)
26
- byebug (9.0.5)
27
- diff-lcs (1.2.5)
28
- i18n (0.7.0)
29
- json (1.8.3)
30
- minitest (5.9.0)
31
- rspec (3.5.0)
32
- rspec-core (~> 3.5.0)
33
- rspec-expectations (~> 3.5.0)
34
- rspec-mocks (~> 3.5.0)
35
- rspec-core (3.5.3)
36
- rspec-support (~> 3.5.0)
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.5.0)
40
- rspec-mocks (3.5.0)
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.5.0)
43
- rspec-support (3.5.0)
44
- thread_safe (0.3.5)
45
- tzinfo (1.2.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.13.1
55
+ 1.15.4
data/README.md CHANGED
@@ -1,27 +1,31 @@
1
- [![Gem Version](https://badge.fury.io/rb/activerecord-prunable.svg)](https://badge.fury.io/rb/activerecord-prunable) [![Build Status](https://travis-ci.org/dr2m/activerecord-prunable.svg?branch=master)](https://travis-ci.org/dr2m/activerecord-prunable) [![Code Climate](https://codeclimate.com/github/dr2m/activerecord-prunable/badges/gpa.svg)](https://codeclimate.com/github/dr2m/activerecord-prunable)
2
-
3
- # Description
1
+ # Activerecord-prunable [![Gem Version](https://badge.fury.io/rb/activerecord-prunable.svg)](https://badge.fury.io/rb/activerecord-prunable) [![Build Status](https://travis-ci.org/dr2m/activerecord-prunable.svg?branch=master)](https://travis-ci.org/dr2m/activerecord-prunable) [![Code Climate](https://codeclimate.com/github/dr2m/activerecord-prunable/badges/gpa.svg)](https://codeclimate.com/github/dr2m/activerecord-prunable)
4
2
 
5
3
  Convenient removal of obsolete ActiveRecord models.
6
4
 
7
- # Installation
5
+ ## Installation
8
6
 
9
- ```ruby
10
- # Gemfile
7
+ Add this line to your application's Gemfile:
11
8
 
12
- gem "activerecord-prunable"
9
+ ```ruby
10
+ gem 'activerecord-prunable'
13
11
  ```
14
12
 
15
- # Usage
13
+ And then execute:
16
14
 
17
- 1. Include the `Prunable` module in the ActiveRecord model that needs to be pruned.
18
- 2. Define the `:prunable` scope that returns models to prune.
15
+ $ bundle
19
16
 
20
- Example:
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
- Pruning a single model:
67
+ __Pruning a single model:__
49
68
 
50
69
  ```ruby
51
70
  SomeModel.prune!
52
71
  ```
53
72
 
54
- Pruning multiple models:
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
- Set default method of pruning (:destroy or :delete):
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
- Call `:prunable` scope with params:
86
+ __Call `:prunable` scope with params:__
67
87
 
68
88
  ```ruby
69
89
  Prunable.prune!(params: [:foo, :bar])
70
90
  ```
71
91
 
72
- Getting an array of all models that include `ActiveRecord::Prunable`:
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
- Pruning all models that include `ActiveRecord::Prunable`:
97
+ __Pruning all models which include `ActiveRecord::Prunable`:__
79
98
 
80
99
  ```ruby
81
100
  Prunable.prune!
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "activerecord-prunable"
3
- spec.version = "0.2.2"
3
+ spec.version = "0.3.0"
4
4
  spec.authors = ["dr2m"]
5
5
  spec.email = ["maletin@maletin.work"]
6
6
 
@@ -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
- return false unless check_prune_method(method)
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 prune!(*params, prune_method: nil)
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 = prunable(*params)
33
- destroyed = prune_by_method(scope, prune_method)
49
+ scope = resolve_scope(*params, current_time)
50
+ destroyed_records = prune_by_method(scope, prune_method)
34
51
 
35
- if destroyed > 0
36
- logger.info "#{destroyed} records have been pruned."
52
+ if destroyed_records > 0
53
+ logger.info "#{destroyed_records} records have been removed."
37
54
  else
38
- logger.info "Nothing to prune."
55
+ logger.info 'Nothing to prune.'
39
56
  end
40
57
 
41
- destroyed
58
+ destroyed_records
42
59
  end
43
60
 
44
61
  private
45
62
 
46
63
  def check_scope(*params)
47
- unless respond_to?(:prunable)
48
- logger.info "This model has no :prunable scope, nothing to prune."
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
- unless prunable(*params).is_a?(::ActiveRecord::Relation)
53
- logger.info ":prunable is not a relation, nothing to prune."
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 check_prune_method(method)
61
- unless [:destroy, :delete].include?(method)
62
- logger.info "Incorrect prune method #{method} will be ignored for #{self}"
63
- return false
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
- true
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
- unless class_variable_defined?(:@@prune_method)
70
- prune_method = prune_method || :destroy
71
- else
72
- prune_method = class_variable_get(:@@prune_method)
73
- end
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
- scope.delete_all
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.2.2
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: 2016-09-24 00:00:00.000000000 Z
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.6.6
118
+ rubygems_version: 2.5.1
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: Convenient removal of obsolete ActiveRecord models.