active_archive 5.1.7 → 5.2.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
  SHA256:
3
- metadata.gz: 02ef56cf163f46d646a5c33c14aaad6597e413faf018434af73e70293ea7bb9a
4
- data.tar.gz: 46d27202b989f81bb8a9bf587d0bd4f6ef701daf18787f2521e6aa0647bfb4e6
3
+ metadata.gz: 7ad44438d97ef3a4c739a8aabb9f9d61429743b9b2835007fdeed270fcf348b6
4
+ data.tar.gz: bb7a6181c2c98a989f5bcbc5465686bde9d0126a5f615c315516d8b005b6046f
5
5
  SHA512:
6
- metadata.gz: a9e6151c972359cca2d7e98ae5e994804905cf0c591554bfae87053cd614e24dfaa75c0081280b62c57d861053cd320126e7b68eb1c7eec6a282412cf1fc86a6
7
- data.tar.gz: d40636590b9f9df38dadc4ce971c15d29c5d7b1bf4a7a5817012b2dd757b4153cff8750238a68a2ab2dea92774e44c2d47a2e5cf35f8ec0803dcaf8837e30d66
6
+ metadata.gz: 893d7bdf1ba645e69c335e99a8b6127b36401d6013bca9ca7f35ea0124177de2dccc78378cd1eb4c57848cd91926ea659dd3db56430906d686a4b41fed50fad9
7
+ data.tar.gz: dab93ef545dcbc4f86f71442d7b2f91ddf05f533adf3c01ee993574382e782c51a44e27faab88b536627006f39c399d2c15dfce72fdd3bf96f5e2c363d9df4af
data/.reek.yml ADDED
@@ -0,0 +1,27 @@
1
+ ---
2
+ detectors:
3
+ Attribute:
4
+ enabled: false
5
+ DuplicateMethodCall:
6
+ enabled: false
7
+ FeatureEnvy:
8
+ enabled: false
9
+ IrresponsibleModule:
10
+ enabled: false
11
+ ManualDispatch:
12
+ enabled: false
13
+ NestedIterators:
14
+ max_allowed_nesting: 2
15
+ NilCheck:
16
+ enabled: false
17
+ TooManyStatements:
18
+ max_statements: 10
19
+ exclude:
20
+ - 'ActiveArchive::Base#retrieve_dependent_records'
21
+ - 'ActiveArchive::Base#set_archived_at'
22
+ UncommunicativeParameterName:
23
+ enabled: false
24
+ UncommunicativeVariableName:
25
+ enabled: false
26
+ UtilityFunction:
27
+ enabled: false
data/.rubocop.yml CHANGED
@@ -12,7 +12,7 @@ Layout/EmptyLinesAroundModuleBody:
12
12
  Enabled: false
13
13
  LineLength:
14
14
  Max: 100
15
- Lint/RescueWithoutErrorClass:
15
+ Lint/HandleExceptions:
16
16
  Enabled: false
17
17
  Lint/ScriptPermission:
18
18
  Enabled: false
@@ -20,7 +20,13 @@ Metrics/MethodLength:
20
20
  Enabled: false
21
21
  Metrics/ModuleLength:
22
22
  Enabled: false
23
+ Naming/AccessorMethodName:
24
+ Enabled: false
23
25
  Style/Alias:
24
26
  EnforcedStyle: prefer_alias_method
25
27
  Style/Documentation:
26
28
  Enabled: false
29
+ Style/ExpandPathArguments:
30
+ Enabled: false
31
+ Style/RescueStandardError:
32
+ Enabled: false
data/README.md CHANGED
@@ -43,12 +43,17 @@ end
43
43
 
44
44
  **Options:**
45
45
  * `archive`
46
+ * `archive_all`
47
+ * `archive_all!`
46
48
  * `destroy`
47
49
  * `destroy_all`
50
+ * `destroy_all!`
48
51
  * `delete`
49
52
  * `delete_all`
50
53
  * `unarchive`
51
54
  * `unarchive_all`
55
+ * `undestroy`
56
+ * `undestroy_all`
52
57
 
53
58
  ```ruby
54
59
  User.first.archive #=> archives User record and dependents
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # coding: utf-8
4
-
5
3
  lib = File.expand_path('../lib', __FILE__)
6
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
7
5
  require 'active_archive/version'
@@ -24,12 +22,12 @@ Gem::Specification.new do |spec|
24
22
  spec.add_runtime_dependency 'rails'
25
23
 
26
24
  spec.add_development_dependency 'bundler'
27
- spec.add_development_dependency 'rake'
28
- spec.add_development_dependency 'rspec'
29
- spec.add_development_dependency 'sqlite3'
30
25
  spec.add_development_dependency 'database_cleaner'
31
- spec.add_development_dependency 'generator_spec'
32
26
  spec.add_development_dependency 'fasterer'
27
+ spec.add_development_dependency 'generator_spec'
28
+ spec.add_development_dependency 'rake'
33
29
  spec.add_development_dependency 'reek'
30
+ spec.add_development_dependency 'rspec'
34
31
  spec.add_development_dependency 'rubocop'
32
+ spec.add_development_dependency 'sqlite3'
35
33
  end
@@ -10,14 +10,33 @@ module ActiveArchive
10
10
  base.instance_eval { define_model_callbacks(:unarchive) }
11
11
  end
12
12
 
13
+ def archivable?
14
+ respond_to?(:archived_at)
15
+ end
16
+
13
17
  def archived?
14
18
  archivable? ? !archived_at.nil? : destroyed?
15
19
  end
16
20
 
17
- def archivable?
18
- respond_to?(:archived_at)
21
+ def unarchived?
22
+ !archived?
23
+ end
24
+
25
+ def unarchivable?
26
+ !archivable?
27
+ end
28
+
29
+ def unarchive(opts = nil)
30
+ with_transaction_returning_status do
31
+ records = should_unarchive_parent_first?(opts) ? unarchival.reverse : unarchival
32
+ records.each { |rec| rec.call(opts) }
33
+
34
+ self
35
+ end
19
36
  end
20
37
 
38
+ alias_method :undestroy, :unarchive
39
+
21
40
  def destroy(force = nil)
22
41
  with_transaction_returning_status do
23
42
  if unarchivable? || should_force_destroy?(force)
@@ -28,36 +47,62 @@ module ActiveArchive
28
47
  end
29
48
  end
30
49
 
31
- alias_method(:archive, :destroy)
32
- alias_method(:archive!, :destroy)
50
+ alias_method :archive, :destroy
33
51
 
34
52
  def to_archival
35
53
  I18n.t("active_archive.archival.#{archived? ? :archived : :unarchived}")
36
54
  end
37
55
 
38
- def unarchive(opts = nil)
39
- with_transaction_returning_status do
40
- records = should_unarchive_parent_first?(opts) ? unarchival.reverse : unarchival
41
- records.each { |rec| rec.call(opts) }
56
+ private
42
57
 
43
- self
44
- end
45
- end
58
+ def unarchival
59
+ [
60
+ lambda do |validate|
61
+ unarchive_destroyed_dependent_records(validate)
62
+ end,
63
+ lambda do |validate|
64
+ run_callbacks(:unarchive) do
65
+ set_archived_at(nil, validate)
46
66
 
47
- alias_method(:unarchive!, :unarchive)
67
+ each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
68
+ assoc_class.increment_counter(counter_cache_column, assoc_id)
69
+ end
48
70
 
49
- def unarchived?
50
- !archived?
71
+ true
72
+ end
73
+ end
74
+ ]
51
75
  end
52
76
 
53
- def unarchivable?
54
- !archivable?
77
+ def get_archived_record
78
+ self.class.unscoped.find(id)
55
79
  end
56
80
 
57
- private
81
+ def set_archived_at(value, force = nil)
82
+ return self unless archivable?
83
+ record = get_archived_record
84
+ record.archived_at = value
58
85
 
59
- def attempt_notifying_observers(callback)
60
- notify_observers(callback) if respond_to?(:notify_observers)
86
+ begin
87
+ should_ignore_validations?(force) ? record.save(validate: false) : record.save!
88
+ @attributes = record.instance_variable_get('@attributes')
89
+ rescue => error
90
+ record.destroy
91
+ raise error
92
+ end
93
+ end
94
+
95
+ def each_counter_cache
96
+ _reflections.each do |name, reflection|
97
+ next unless respond_to?(name.to_sym)
98
+
99
+ association = send(name.to_sym)
100
+
101
+ next if association.nil?
102
+ next unless reflection.belongs_to? && reflection.counter_cache_column
103
+
104
+ yield(association.class, reflection.counter_cache_column, send(reflection.foreign_key))
105
+ end
61
106
  end
62
107
 
63
108
  def destroy_with_active_archive(force = nil)
@@ -66,53 +111,74 @@ module ActiveArchive
66
111
  save
67
112
  else
68
113
  set_archived_at(Time.now, force)
114
+
69
115
  each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
70
116
  assoc_class.decrement_counter(counter_cache_column, assoc_id)
71
117
  end
72
118
  end
73
- return(true)
119
+
120
+ true
74
121
  end
75
122
 
76
123
  archived? ? self : false
77
124
  end
78
125
 
79
- def each_counter_cache
80
- _reflections.each do |name, reflection|
81
- next unless respond_to?(name.to_sym)
82
-
83
- association = send(name.to_sym)
84
-
85
- next if association.nil?
86
- next unless reflection.belongs_to? && reflection.counter_cache_column
126
+ def add_record_window(_request, name, reflection)
127
+ qtn = reflection.table_name
128
+ window = ActiveArchive.configuration.dependent_record_window
129
+ query = "#{qtn}.archived_at > ? AND #{qtn}.archived_at < ?"
87
130
 
88
- associated_class = association.class
131
+ send(name).unscope(where: :archived_at)
132
+ .where(query, archived_at - window, archived_at + window)
133
+ end
89
134
 
90
- yield(associated_class, reflection.counter_cache_column, send(reflection.foreign_key))
135
+ def unarchive_destroyed_dependent_records(force = nil)
136
+ destroyed_dependent_relations.each do |relation|
137
+ relation.to_a.each do |destroyed_dependent_record|
138
+ destroyed_dependent_record.try(:unarchive, force)
139
+ end
91
140
  end
92
- end
93
141
 
94
- def retrieve_archived_record
95
- self.class.unscoped.find(id)
142
+ reload
96
143
  end
97
144
 
98
145
  # rubocop:disable Metrics/AbcSize
99
- def retrieve_dependent_records
100
- dependent_records = {}
101
-
102
- self.class.reflections.each do |key, ref|
103
- next unless ref.options[:dependent] == :destroy
146
+ def destroyed_dependent_relations
147
+ dependent_permanent_reflections(self.class).map do |name, relation|
148
+ case relation.macro.to_s.gsub('has_', '').to_sym
149
+ when :many
150
+ if archived_at
151
+ add_record_window(send(name), name, relation)
152
+ else
153
+ send(name).unscope(where: :archived_at)
154
+ end
155
+ when :one, :belongs_to
156
+ self.class.unscoped { Array(send(name)) }
157
+ end
158
+ end
159
+ end
160
+ # rubocop:enable Metrics/AbcSize
104
161
 
105
- records = send(key)
106
- next unless records
107
- records.respond_to?(:empty?) ? (next if records.empty?) : (records = [] << records)
162
+ def attempt_notifying_observers(callback)
163
+ notify_observers(callback)
164
+ rescue NoMethodError
165
+ # do nothing
166
+ end
108
167
 
109
- dependent_record = records.first
110
- dependent_record.nil? ? next : dependent_records[dependent_record.class] = records.map(&:id)
168
+ def dependent_record_ids
169
+ dependent_reflections(self.class).reduce({}) do |records, (key, _)|
170
+ found = Array(send(key)).compact
171
+ next records if found.empty?
172
+ records.update(found.first.class => found.map(&:id))
111
173
  end
174
+ end
112
175
 
113
- dependent_records
176
+ def permanently_delete_records_after(&block)
177
+ dependent_records = dependent_record_ids
178
+ result = yield(block)
179
+ permanently_delete_records(dependent_records) if result
180
+ result
114
181
  end
115
- # rubocop:enable Metrics/AbcSize
116
182
 
117
183
  def permanently_delete_records(dependent_records)
118
184
  dependent_records.each do |klass, ids|
@@ -125,89 +191,18 @@ module ActiveArchive
125
191
  end
126
192
  end
127
193
 
128
- def permanently_delete_records_after(&block)
129
- dependent_records = retrieve_dependent_records
130
- dependent_results = yield(block)
131
- permanently_delete_records(dependent_records) if dependent_results
132
- dependent_results
133
- end
134
-
135
- def unarchival
136
- [
137
- ->(validate) { unarchive_destroyed_dependent_records(validate) },
138
- lambda do |validate|
139
- run_callbacks(:unarchive) do
140
- set_archived_at(nil, validate)
141
- each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
142
- assoc_class.increment_counter(counter_cache_column, assoc_id)
143
- end
144
- return(true)
145
- end
146
- end
147
- ]
148
- end
149
-
150
- # rubocop:disable Metrics/LineLength
151
- def dependent_records_for_unarchival(name, reflection)
152
- record = send(name)
153
-
154
- case reflection.macro.to_s.gsub('has_', '').to_sym
155
- when :many
156
- records = archived_at ? set_record_window(record, name, reflection) : record.unscope(where: :archived_at)
157
- when :one, :belongs_to
158
- self.class.unscoped { records = [] << record }
194
+ def dependent_reflections(klass)
195
+ klass.reflections.select do |_, reflection|
196
+ reflection.options[:dependent] == :destroy
159
197
  end
160
-
161
- [records].flatten.compact
162
198
  end
163
- # rubocop:enable Metrics/LineLength
164
199
 
165
- def unarchive_destroyed_dependent_records(force = nil)
166
- self.class.reflections
167
- .select { |_, ref| ref.options[:dependent].to_s == 'destroy' && ref.klass.archivable? }
168
- .each do |name, ref|
169
- dependent_records_for_unarchival(name, ref).each { |rec| rec.try(:unarchive, force) }
170
- reload
171
- end
172
- end
173
-
174
- def set_archived_at(value, force = nil)
175
- return self unless archivable?
176
- record = retrieve_archived_record
177
- record.archived_at = value
178
-
179
- begin
180
- should_ignore_validations?(force) ? record.save(validate: false) : record.save!
181
-
182
- if ::ActiveRecord::VERSION::MAJOR >= 5 && ::ActiveRecord::VERSION::MINOR >= 2
183
- @mutations_before_last_save = record.send(:mutations_from_database)
184
- @attributes_changed_by_setter = HashWithIndifferentAccess.new
185
- elsif ::ActiveRecord::VERSION::MAJOR >= 5
186
- @previous_mutation_tracker = record.send(:previous_mutation_tracker)
187
- elsif ::ActiveRecord::VERSION::MAJOR >= 4
188
- @previously_changed = record.instance_variable_get('@previously_changed')
189
- end
190
-
191
- @changed_attributes = HashWithIndifferentAccess.new
192
- @attributes = record.instance_variable_get('@attributes')
193
- @mutation_tracker = nil
194
- @mutations_from_database = nil
195
- rescue => error
196
- record.destroy
197
- raise(error)
200
+ def dependent_permanent_reflections(klass)
201
+ dependent_reflections(klass).select do |_name, reflection|
202
+ reflection.klass.archivable?
198
203
  end
199
204
  end
200
205
 
201
- def set_record_window(_, name, reflection)
202
- qtn = reflection.table_name
203
- window = ActiveArchive.configuration.dependent_record_window
204
-
205
- query = "#{qtn}.archived_at > ? AND #{qtn}.archived_at < ?"
206
-
207
- send(name).unscope(where: :archived_at)
208
- .where([query, archived_at - window, archived_at + window])
209
- end
210
-
211
206
  def should_force_destroy?(force)
212
207
  force.is_a?(Hash) ? force[:force] : (force == :force)
213
208
  end
@@ -8,12 +8,20 @@ module ActiveArchive
8
8
  end
9
9
 
10
10
  def archive_all(conditions = nil)
11
- conditions ? where(conditions).destroy_all : destroy_all
11
+ (conditions ? where(conditions) : all).to_a.each(&:archive)
12
12
  end
13
13
 
14
+ def archive_all!(conditions = nil)
15
+ (conditions ? where(conditions) : all).to_a.each { |r| r.send(:archive, :force) }
16
+ end
17
+
18
+ alias_method :destroy_all!, :archive_all!
19
+
14
20
  def unarchive_all(conditions = nil)
15
21
  (conditions ? where(conditions) : all).to_a.each(&:unarchive)
16
22
  end
17
23
 
24
+ alias_method :undestroy_all, :unarchive_all
25
+
18
26
  end
19
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveArchive
4
- VERSION ||= '5.1.7'
4
+ VERSION ||= '5.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_archive
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.7
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-04 00:00:00.000000000 Z
11
+ date: 2018-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: database_cleaner
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: fasterer
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: sqlite3
70
+ name: generator_spec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: database_cleaner
84
+ name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: generator_spec
98
+ name: reek
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: fasterer
112
+ name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -123,7 +123,7 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: reek
126
+ name: rubocop
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: rubocop
140
+ name: sqlite3
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
@@ -160,7 +160,7 @@ files:
160
160
  - ".DS_Store"
161
161
  - ".fasterer.yml"
162
162
  - ".gitignore"
163
- - ".reek"
163
+ - ".reek.yml"
164
164
  - ".rspec"
165
165
  - ".rubocop.yml"
166
166
  - ".travis.yml"
data/.reek DELETED
@@ -1,22 +0,0 @@
1
- ---
2
- Attribute:
3
- enabled: false
4
- DuplicateMethodCall:
5
- enabled: false
6
- FeatureEnvy:
7
- enabled: false
8
- IrresponsibleModule:
9
- enabled: false
10
- ManualDispatch:
11
- enabled: false
12
- NestedIterators:
13
- max_allowed_nesting: 2
14
- NilCheck:
15
- enabled: false
16
- TooManyStatements:
17
- max_statements: 10
18
- exclude:
19
- - 'ActiveArchive::Base#retrieve_dependent_records'
20
- - 'ActiveArchive::Base#set_archived_at'
21
- UtilityFunction:
22
- enabled: false