active_record-undo 0.2.0 → 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/CHANGELOG.md +78 -2
- data/DOCUMENTATION.md +311 -178
- data/README.md +140 -10
- data/app/controllers/active_record/undo/application_controller.rb +9 -0
- data/app/controllers/active_record/undo/logs_controller/async_handler.rb +50 -0
- data/app/controllers/active_record/undo/logs_controller.rb +32 -3
- data/app/jobs/active_record/undo/restore_job.rb +72 -0
- data/app/jobs/active_record/undo/soft_delete_job.rb +75 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20260920000000_add_status_and_error_message_to_undo_logs.rb +15 -0
- data/lib/active_record/undo/cascade_handler.rb +66 -0
- data/lib/active_record/undo/configuration.rb +2 -1
- data/lib/active_record/undo/model_extension/async_methods.rb +68 -0
- data/lib/active_record/undo/model_extension.rb +7 -4
- data/lib/active_record/undo/status_predicates.rb +39 -0
- data/lib/active_record/undo/undo_log/token_verifier.rb +48 -0
- data/lib/active_record/undo/undo_log.rb +49 -32
- data/lib/active_record/undo/version.rb +1 -1
- data/lib/active_record/undo/view_helpers/status_badge_helper.rb +84 -0
- data/lib/active_record/undo/view_helpers.rb +4 -0
- data/lib/active_record/undo.rb +24 -1
- data/sig/active_record/undo.rbs +50 -1
- metadata +23 -1
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
require_relative 'cascade_handler'
|
|
5
5
|
require_relative 'model_extension/attribution_helper'
|
|
6
6
|
require_relative 'model_extension/tenant_verification'
|
|
7
|
+
require_relative 'model_extension/async_methods'
|
|
7
8
|
|
|
8
9
|
module ActiveRecord
|
|
9
10
|
module Undo
|
|
@@ -53,6 +54,8 @@ module ActiveRecord
|
|
|
53
54
|
module InstanceMethods
|
|
54
55
|
include AttributionHelper
|
|
55
56
|
include TenantVerification
|
|
57
|
+
include AsyncMethods
|
|
58
|
+
include StatusPredicates
|
|
56
59
|
|
|
57
60
|
def soft_deleted?
|
|
58
61
|
public_send(self.class.undoable_column).present?
|
|
@@ -71,10 +74,10 @@ module ActiveRecord
|
|
|
71
74
|
def undoable?
|
|
72
75
|
return false unless persisted? && soft_deleted?
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
)
|
|
77
|
+
log = undo_log
|
|
78
|
+
return false unless log
|
|
79
|
+
|
|
80
|
+
log.respond_to?(:completed?) ? log.completed? : true
|
|
78
81
|
end
|
|
79
82
|
|
|
80
83
|
def undo_log
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Undo
|
|
5
|
+
module StatusPredicates
|
|
6
|
+
def soft_delete_pending?
|
|
7
|
+
soft_delete_status == 'pending'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def soft_delete_processing?
|
|
11
|
+
soft_delete_status == 'processing'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def soft_delete_completed?
|
|
15
|
+
soft_delete_status == 'completed'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def soft_delete_failed?
|
|
19
|
+
soft_delete_status == 'failed'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def restore_pending?
|
|
23
|
+
restore_status == 'pending'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def restore_processing?
|
|
27
|
+
restore_status == 'processing'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def restore_completed?
|
|
31
|
+
restore_status == 'completed'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def restore_failed?
|
|
35
|
+
restore_status == 'failed'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/message_verifier'
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module Undo
|
|
7
|
+
class UndoLog < ActiveRecord::Base
|
|
8
|
+
module TokenVerifier
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
class_methods do
|
|
12
|
+
def find_by_signed_token(token, purpose: :restore)
|
|
13
|
+
return nil unless token.is_a?(String) && token.present?
|
|
14
|
+
|
|
15
|
+
verified_id = verify_signed_token(token, purpose: purpose)
|
|
16
|
+
return nil unless verified_id
|
|
17
|
+
|
|
18
|
+
find_by(id: verified_id)
|
|
19
|
+
rescue StandardError
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def verify_signed_token(token, purpose: :restore)
|
|
24
|
+
return nil unless token.is_a?(String) && token.present?
|
|
25
|
+
|
|
26
|
+
token_verifier.verified(token, purpose: purpose)
|
|
27
|
+
rescue StandardError
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def token_verifier
|
|
32
|
+
if defined?(Rails.application) && Rails.application.respond_to?(:message_verifier)
|
|
33
|
+
Rails.application.message_verifier(:active_record_undo)
|
|
34
|
+
else
|
|
35
|
+
key = ActiveRecord::Undo.config.token_secret_key || 'active_record_undo_default_secret_key_32_bytes'
|
|
36
|
+
@token_verifier ||= ActiveSupport::MessageVerifier.new(key, digest: 'SHA256')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def signed_token(expires_in: ActiveRecord::Undo.config.token_expires_in, purpose: :restore)
|
|
42
|
+
self.class.token_verifier.generate(id, purpose: purpose, expires_in: expires_in)
|
|
43
|
+
end
|
|
44
|
+
alias to_signed_token signed_token
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative 'undo_log/token_verifier'
|
|
4
4
|
|
|
5
5
|
module ActiveRecord
|
|
6
6
|
module Undo
|
|
@@ -9,12 +9,17 @@ module ActiveRecord
|
|
|
9
9
|
|
|
10
10
|
include ModelExtension::AttributionHelper
|
|
11
11
|
include ModelExtension::TenantVerification
|
|
12
|
+
include TokenVerifier
|
|
13
|
+
include StatusPredicates
|
|
12
14
|
|
|
13
15
|
has_many :undo_log_items, class_name: 'ActiveRecord::Undo::UndoLogItem', dependent: :destroy
|
|
14
16
|
|
|
15
17
|
belongs_to :whodunnit, polymorphic: true, optional: true
|
|
16
18
|
belongs_to :tenant, polymorphic: true, optional: true
|
|
17
19
|
|
|
20
|
+
enum :status, { pending: 0, processing: 1, completed: 2, failed: 3 }, default: :completed
|
|
21
|
+
enum :action, { soft_delete: 0, restore: 1 }, default: :soft_delete
|
|
22
|
+
|
|
18
23
|
scope :for_whodunnit, lambda { |user|
|
|
19
24
|
if user.is_a?(ActiveRecord::Base)
|
|
20
25
|
where(whodunnit: user)
|
|
@@ -40,50 +45,39 @@ module ActiveRecord
|
|
|
40
45
|
end
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
def
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
verified_id = verify_signed_token(token, purpose: purpose)
|
|
47
|
-
return nil unless verified_id
|
|
48
|
+
def expired?
|
|
49
|
+
period = ActiveRecord::Undo.config.retention_period
|
|
50
|
+
return false unless period && created_at
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
rescue StandardError
|
|
51
|
-
nil
|
|
52
|
+
created_at < Time.current - period
|
|
52
53
|
end
|
|
53
54
|
|
|
54
|
-
def
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
token_verifier.verified(token, purpose: purpose)
|
|
58
|
-
rescue StandardError
|
|
59
|
-
nil
|
|
60
|
-
end
|
|
55
|
+
def soft_delete_status
|
|
56
|
+
return status if action == 'soft_delete' || action.nil?
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
if defined?(Rails.application) && Rails.application.respond_to?(:message_verifier)
|
|
64
|
-
Rails.application.message_verifier(:active_record_undo)
|
|
65
|
-
else
|
|
66
|
-
key = ActiveRecord::Undo.config.token_secret_key || 'active_record_undo_default_secret_key_32_bytes'
|
|
67
|
-
@token_verifier ||= ActiveSupport::MessageVerifier.new(key, digest: 'SHA256')
|
|
68
|
-
end
|
|
58
|
+
'completed'
|
|
69
59
|
end
|
|
70
60
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
return false unless period && created_at
|
|
61
|
+
def restore_status
|
|
62
|
+
return status if action == 'restore'
|
|
74
63
|
|
|
75
|
-
|
|
64
|
+
nil
|
|
76
65
|
end
|
|
77
66
|
|
|
78
|
-
def
|
|
79
|
-
|
|
67
|
+
def restore_later!(whodunnit: nil, queue: nil)
|
|
68
|
+
verify_restore_preconditions!
|
|
69
|
+
with_lock do
|
|
70
|
+
validate_restore_status_eligibility!
|
|
71
|
+
update!(action: :restore, status: :pending)
|
|
72
|
+
end
|
|
73
|
+
enqueue_restore_job!(whodunnit, queue)
|
|
74
|
+
self
|
|
80
75
|
end
|
|
81
|
-
alias to_signed_token signed_token
|
|
82
76
|
|
|
83
77
|
# Restores all records associated with this deletion batch
|
|
84
78
|
def restore!(whodunnit: nil)
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
verify_restore_preconditions!
|
|
80
|
+
validate_restore_status_eligibility!
|
|
87
81
|
|
|
88
82
|
actor = resolve_whodunnit(whodunnit)
|
|
89
83
|
with_whodunnit_context(actor) do
|
|
@@ -93,6 +87,29 @@ module ActiveRecord
|
|
|
93
87
|
|
|
94
88
|
private
|
|
95
89
|
|
|
90
|
+
def verify_restore_preconditions!
|
|
91
|
+
ActiveRecord::Undo.verify_configured_context!
|
|
92
|
+
verify_tenant_match!(self) if tenant_present?
|
|
93
|
+
raise ActiveRecord::Undo::Error, 'Undo action has expired.' if expired?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def validate_restore_status_eligibility!
|
|
97
|
+
raise ActiveRecord::Undo::Error, 'Cannot restore: UndoLog is currently processing.' if processing?
|
|
98
|
+
|
|
99
|
+
if pending? && action == 'restore'
|
|
100
|
+
raise ActiveRecord::Undo::Error, 'Cannot restore: UndoLog is already scheduled for restore.'
|
|
101
|
+
end
|
|
102
|
+
return if completed? || (action == 'restore' && failed?)
|
|
103
|
+
|
|
104
|
+
raise ActiveRecord::Undo::Error, "Cannot restore: UndoLog is not completed (current status: #{status})."
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def enqueue_restore_job!(whodunnit, queue)
|
|
108
|
+
job_class = ActiveRecord::Undo::RestoreJob
|
|
109
|
+
job = queue.present? ? job_class.set(queue: queue) : job_class
|
|
110
|
+
job.perform_later(id, whodunnit: whodunnit)
|
|
111
|
+
end
|
|
112
|
+
|
|
96
113
|
def tenant_present?
|
|
97
114
|
tenant_id.present? || tenant_type.present?
|
|
98
115
|
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Undo
|
|
5
|
+
module ViewHelpers
|
|
6
|
+
module StatusBadgeHelper
|
|
7
|
+
def undo_status_badge(target, action: :auto, **html_options)
|
|
8
|
+
return nil if target.nil?
|
|
9
|
+
|
|
10
|
+
act, status = resolve_target_action_and_status(target, action)
|
|
11
|
+
return nil unless status
|
|
12
|
+
|
|
13
|
+
classes = build_badge_classes(act, status, html_options.delete(:class))
|
|
14
|
+
label = html_options.delete(:text) || status.to_s.humanize
|
|
15
|
+
render_badge_tag(label, classes, html_options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def soft_delete_status_badge(target, **html_options)
|
|
19
|
+
undo_status_badge(target, action: :soft_delete, **html_options)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def restore_status_badge(target, **html_options)
|
|
23
|
+
undo_status_badge(target, action: :restore, **html_options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def resolve_target_action_and_status(target, action)
|
|
29
|
+
return nil if target.nil?
|
|
30
|
+
|
|
31
|
+
case action
|
|
32
|
+
when :soft_delete
|
|
33
|
+
['soft_delete', extract_target_status(target, :soft_delete_status)]
|
|
34
|
+
when :restore
|
|
35
|
+
['restore', extract_target_status(target, :restore_status)]
|
|
36
|
+
else
|
|
37
|
+
resolve_auto_action_and_status(target)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def extract_target_status(target, status_method)
|
|
42
|
+
if target.respond_to?(status_method)
|
|
43
|
+
target.public_send(status_method)
|
|
44
|
+
elsif target.respond_to?(:status)
|
|
45
|
+
target.status
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def resolve_auto_action_and_status(target)
|
|
50
|
+
return ['restore', target.restore_status] if auto_restore_status?(target)
|
|
51
|
+
return ['soft_delete', target.soft_delete_status] if auto_soft_delete_status?(target)
|
|
52
|
+
return [log_action(target), target.status] if target.respond_to?(:status)
|
|
53
|
+
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def auto_restore_status?(target)
|
|
58
|
+
target.respond_to?(:restore_status) && target.restore_status.present?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def auto_soft_delete_status?(target)
|
|
62
|
+
target.respond_to?(:soft_delete_status) && target.soft_delete_status.present?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def log_action(target)
|
|
66
|
+
target.respond_to?(:action) ? target.action : nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build_badge_classes(action, status, custom_class)
|
|
70
|
+
action_class = action ? "undo-#{action.to_s.tr('_', '-')}-badge" : nil
|
|
71
|
+
['undo-status-badge', action_class, "undo-status-#{status}", custom_class].compact.join(' ')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def render_badge_tag(label, classes, html_options)
|
|
75
|
+
if respond_to?(:content_tag)
|
|
76
|
+
content_tag(:span, label, html_options.merge(class: classes))
|
|
77
|
+
else
|
|
78
|
+
"<span class=\"#{classes}\">#{label}</span>"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'view_helpers/status_badge_helper'
|
|
4
|
+
|
|
3
5
|
module ActiveRecord
|
|
4
6
|
module Undo
|
|
5
7
|
module ViewHelpers
|
|
8
|
+
include StatusBadgeHelper
|
|
9
|
+
|
|
6
10
|
def undo_button_to(target, text = nil, signed: false, **html_options)
|
|
7
11
|
btn_text = extract_undo_text(text, html_options)
|
|
8
12
|
url = resolve_undo_path(target, signed: signed)
|
data/lib/active_record/undo.rb
CHANGED
|
@@ -15,11 +15,11 @@ require_relative 'undo/engine' if defined?(Rails::Engine)
|
|
|
15
15
|
require_relative 'undo/view_helpers' if defined?(ActionView)
|
|
16
16
|
require_relative 'undo/configuration'
|
|
17
17
|
require_relative 'undo/safe_redirect'
|
|
18
|
+
require_relative 'undo/status_predicates'
|
|
18
19
|
require_relative 'undo/model_extension'
|
|
19
20
|
require_relative 'undo/undo_log'
|
|
20
21
|
require_relative 'undo/undo_log_item'
|
|
21
22
|
require_relative 'undo/purger'
|
|
22
|
-
require_relative 'undo/purge_job'
|
|
23
23
|
|
|
24
24
|
module ActiveRecord
|
|
25
25
|
module Undo
|
|
@@ -98,6 +98,17 @@ module ActiveRecord
|
|
|
98
98
|
defined?(ActionController::Base) ? ActionController::Base : Object
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
+
def base_job_class
|
|
102
|
+
configured = config.base_job
|
|
103
|
+
return configured if configured.is_a?(Class)
|
|
104
|
+
|
|
105
|
+
(configured.presence && configured.to_s.safe_constantize) || default_base_job
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def default_base_job
|
|
109
|
+
defined?(ActiveJob::Base) ? ActiveJob::Base : Object
|
|
110
|
+
end
|
|
111
|
+
|
|
101
112
|
private
|
|
102
113
|
|
|
103
114
|
def eager_load_rails!
|
|
@@ -111,6 +122,18 @@ module ActiveRecord
|
|
|
111
122
|
end
|
|
112
123
|
end
|
|
113
124
|
|
|
125
|
+
begin
|
|
126
|
+
require 'active_job'
|
|
127
|
+
rescue LoadError
|
|
128
|
+
# ActiveJob is optional
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
if defined?(ActiveJob::Base)
|
|
132
|
+
require_relative 'undo/purge_job'
|
|
133
|
+
require_relative '../../app/jobs/active_record/undo/soft_delete_job'
|
|
134
|
+
require_relative '../../app/jobs/active_record/undo/restore_job'
|
|
135
|
+
end
|
|
136
|
+
|
|
114
137
|
if defined?(ActiveSupport)
|
|
115
138
|
ActiveSupport.on_load(:active_record) do
|
|
116
139
|
include ActiveRecord::Undo::ModelExtension
|
data/sig/active_record/undo.rbs
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
module ActiveRecord
|
|
2
2
|
module Undo
|
|
3
3
|
VERSION: String
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
class Error < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class SecurityError < Error
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.whodunnit: () -> untyped
|
|
12
|
+
def self.whodunnit=: (untyped) -> untyped
|
|
13
|
+
def self.current_tenant: () -> untyped
|
|
14
|
+
def self.current_tenant=: (untyped) -> untyped
|
|
15
|
+
def self.config: () -> Configuration
|
|
16
|
+
def self.configure: () { (Configuration) -> void } -> void
|
|
17
|
+
def self.registered_models: () -> Set[untyped]
|
|
18
|
+
def self.undoable_models: () -> Array[untyped]
|
|
19
|
+
def self.base_controller_class: () -> untyped
|
|
20
|
+
def self.base_job_class: () -> untyped
|
|
21
|
+
|
|
22
|
+
class Configuration
|
|
23
|
+
attr_accessor retention_period: untyped
|
|
24
|
+
attr_accessor current_user_method: untyped
|
|
25
|
+
attr_accessor current_tenant_method: untyped
|
|
26
|
+
attr_accessor base_controller: untyped
|
|
27
|
+
attr_accessor base_job: untyped
|
|
28
|
+
attr_accessor default_redirect_path: untyped
|
|
29
|
+
attr_accessor token_secret_key: String?
|
|
30
|
+
attr_accessor token_expires_in: untyped
|
|
31
|
+
attr_accessor error_handling: Symbol
|
|
32
|
+
|
|
33
|
+
def initialize: () -> void
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module StatusPredicates
|
|
37
|
+
def soft_delete_pending?: () -> bool
|
|
38
|
+
def soft_delete_processing?: () -> bool
|
|
39
|
+
def soft_delete_completed?: () -> bool
|
|
40
|
+
def soft_delete_failed?: () -> bool
|
|
41
|
+
def restore_pending?: () -> bool
|
|
42
|
+
def restore_processing?: () -> bool
|
|
43
|
+
def restore_completed?: () -> bool
|
|
44
|
+
def restore_failed?: () -> bool
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module ViewHelpers
|
|
48
|
+
def undo_button_to: (untyped target, ?String? text, ?signed: bool, **untyped html_options) -> untyped
|
|
49
|
+
def undo_link_to: (untyped target, ?String? text, ?signed: bool, **untyped html_options) -> untyped
|
|
50
|
+
def undo_status_badge: (untyped target, ?action: Symbol, **untyped html_options) -> untyped
|
|
51
|
+
def soft_delete_status_badge: (untyped target, **untyped html_options) -> untyped
|
|
52
|
+
def restore_status_badge: (untyped target, **untyped html_options) -> untyped
|
|
53
|
+
end
|
|
5
54
|
end
|
|
6
55
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_record-undo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Saurabh Sharma
|
|
@@ -9,6 +9,20 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activejob
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 7.0.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 7.0.0
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: activerecord
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -138,10 +152,14 @@ files:
|
|
|
138
152
|
- Rakefile
|
|
139
153
|
- app/controllers/active_record/undo/application_controller.rb
|
|
140
154
|
- app/controllers/active_record/undo/logs_controller.rb
|
|
155
|
+
- app/controllers/active_record/undo/logs_controller/async_handler.rb
|
|
141
156
|
- app/controllers/active_record/undo/restores_controller.rb
|
|
157
|
+
- app/jobs/active_record/undo/restore_job.rb
|
|
158
|
+
- app/jobs/active_record/undo/soft_delete_job.rb
|
|
142
159
|
- config/routes.rb
|
|
143
160
|
- db/migrate/20260808000000_create_active_record_undo_tables.rb
|
|
144
161
|
- db/migrate/20260821000000_add_tenant_and_user_attribution_to_undo_logs.rb
|
|
162
|
+
- db/migrate/20260920000000_add_status_and_error_message_to_undo_logs.rb
|
|
145
163
|
- lib/active_record/undo.rb
|
|
146
164
|
- lib/active_record/undo/cascade_handler.rb
|
|
147
165
|
- lib/active_record/undo/cascade_handler/association_finder.rb
|
|
@@ -149,17 +167,21 @@ files:
|
|
|
149
167
|
- lib/active_record/undo/configuration.rb
|
|
150
168
|
- lib/active_record/undo/engine.rb
|
|
151
169
|
- lib/active_record/undo/model_extension.rb
|
|
170
|
+
- lib/active_record/undo/model_extension/async_methods.rb
|
|
152
171
|
- lib/active_record/undo/model_extension/attribution_helper.rb
|
|
153
172
|
- lib/active_record/undo/model_extension/tenant_verification.rb
|
|
154
173
|
- lib/active_record/undo/purge_job.rb
|
|
155
174
|
- lib/active_record/undo/purger.rb
|
|
156
175
|
- lib/active_record/undo/purger/reflection_helper.rb
|
|
157
176
|
- lib/active_record/undo/safe_redirect.rb
|
|
177
|
+
- lib/active_record/undo/status_predicates.rb
|
|
158
178
|
- lib/active_record/undo/tasks/purge.rake
|
|
159
179
|
- lib/active_record/undo/undo_log.rb
|
|
180
|
+
- lib/active_record/undo/undo_log/token_verifier.rb
|
|
160
181
|
- lib/active_record/undo/undo_log_item.rb
|
|
161
182
|
- lib/active_record/undo/version.rb
|
|
162
183
|
- lib/active_record/undo/view_helpers.rb
|
|
184
|
+
- lib/active_record/undo/view_helpers/status_badge_helper.rb
|
|
163
185
|
- lib/tasks/active_record_undo_tasks.rake
|
|
164
186
|
- sig/active_record/undo.rbs
|
|
165
187
|
homepage: https://github.com/saurabh-activecode/active_record-undo
|