active_capture 1.1.2 → 1.1.3
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/lib/active_capture.rb +22 -0
- data/lib/support/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 408cdbd0f3cea245a023857573782eab133c6f8d3a41981ff190702c8f6424bb
|
4
|
+
data.tar.gz: 9726c3c013f766036550a1170d8f4b71f382043058e78701fee884654b002f6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08763c65b1bf808fbf85677e912621e34ffc2d00de886a6242f1bdc5308e425215e293d471403a6bc14c51b92bab82d4c2e6cf652421192c66977a2cd4c46a7e'
|
7
|
+
data.tar.gz: 6dfbb8e4974cc7382d5b6999413643d7483586843582eba130424ba0929519855f9d0519a14615ac0c37dfdea593bb6e73f353d0130f710e03836069e81d0bab
|
data/lib/active_capture.rb
CHANGED
@@ -4,6 +4,7 @@ require 'json'
|
|
4
4
|
require 'active_record'
|
5
5
|
|
6
6
|
module ActiveCapture
|
7
|
+
# Captures the state of a record and its associations
|
7
8
|
def self.take(record, associations: [], name: nil)
|
8
9
|
validate_record(record)
|
9
10
|
|
@@ -15,18 +16,21 @@ module ActiveCapture
|
|
15
16
|
}
|
16
17
|
|
17
18
|
begin
|
19
|
+
# Save the captured data in json file
|
18
20
|
Support::CaptureStorage.save_capture(record, capture_data, name)
|
19
21
|
rescue StandardError => e
|
20
22
|
raise "Failed to save capture: #{e.message}"
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
26
|
+
# Restores a record and its associations from a capture file
|
24
27
|
def self.restore(record, capture_file, merge: false)
|
25
28
|
captured_records = Support::CaptureStorage.load_capture(capture_file)
|
26
29
|
validate_capture(record, captured_records)
|
27
30
|
|
28
31
|
ActiveRecord::Base.transaction do
|
29
32
|
begin
|
33
|
+
# Update the record's attributes and restore its associations
|
30
34
|
record.update!(captured_records['attributes'])
|
31
35
|
restore_associations(record, captured_records['associations'], merge: merge)
|
32
36
|
rescue StandardError => e
|
@@ -35,24 +39,28 @@ module ActiveCapture
|
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
42
|
+
# Flushes all captured data of a specified directory
|
38
43
|
def self.flush(directory)
|
39
44
|
Support::CaptureStorage.flush(directory)
|
40
45
|
end
|
41
46
|
|
42
47
|
private
|
43
48
|
|
49
|
+
# Validates that the given record is an ActiveRecord instance
|
44
50
|
def self.validate_record(record)
|
45
51
|
unless record.is_a?(ActiveRecord::Base)
|
46
52
|
raise ArgumentError, 'Record must be an ActiveRecord::Base instance'
|
47
53
|
end
|
48
54
|
end
|
49
55
|
|
56
|
+
# Validates that the capture file matches the given record
|
50
57
|
def self.validate_capture(record, captured_records)
|
51
58
|
unless captured_records['record_id'] == record.id
|
52
59
|
raise ArgumentError, 'Capture file does not match the given record'
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
63
|
+
# Captures the specified associations of a record
|
56
64
|
def self.capture_associations(record, associations)
|
57
65
|
associations.each_with_object({}) do |association, association_data|
|
58
66
|
association_name, nested_associations = parse_association(association)
|
@@ -60,6 +68,7 @@ module ActiveCapture
|
|
60
68
|
next unless record.respond_to?(association_name)
|
61
69
|
|
62
70
|
begin
|
71
|
+
# Capture the related records for the association
|
63
72
|
related_records = record.send(association_name)
|
64
73
|
association_data[association_name] = capture_related_records(related_records, nested_associations)
|
65
74
|
rescue StandardError => e
|
@@ -68,6 +77,7 @@ module ActiveCapture
|
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
80
|
+
# Captures the attributes and nested associations of related records
|
71
81
|
def self.capture_related_records(related_records, nested_associations)
|
72
82
|
if related_records.is_a?(ActiveRecord::Base)
|
73
83
|
{
|
@@ -84,6 +94,7 @@ module ActiveCapture
|
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
97
|
+
# Parses an association to extract its name and nested associations
|
87
98
|
def self.parse_association(association)
|
88
99
|
if association.is_a?(Hash)
|
89
100
|
[association.keys.first, association.values.flatten]
|
@@ -92,36 +103,44 @@ module ActiveCapture
|
|
92
103
|
end
|
93
104
|
end
|
94
105
|
|
106
|
+
# Restores the associations of a record from captured data
|
95
107
|
def self.restore_associations(record, associations_data, merge: false)
|
96
108
|
associations_data.each do |association_name, related_data|
|
97
109
|
if related_data.is_a?(Array)
|
110
|
+
# Restore a collection association (e.g., has_many)
|
98
111
|
restore_collection_association(record, association_name, related_data, merge)
|
99
112
|
else
|
113
|
+
# Restore a single association (e.g., belongs_to, has_one)
|
100
114
|
restore_single_association(record, association_name, related_data, merge)
|
101
115
|
end
|
102
116
|
end
|
103
117
|
end
|
104
118
|
|
119
|
+
# Restores a collection association (e.g., has_many)
|
105
120
|
def self.restore_collection_association(record, association_name, related_data, merge)
|
106
121
|
associated_class = record.class.reflect_on_association(association_name).klass
|
107
122
|
existing_records = record.send(association_name)
|
108
123
|
|
109
124
|
related_data.each do |related_record_data|
|
110
125
|
if merge && related_record_data['attributes']['id']
|
126
|
+
# Update existing records if merging is enabled
|
111
127
|
existing_record = existing_records.find_by(id: related_record_data['attributes']['id'])
|
112
128
|
if existing_record
|
113
129
|
update_and_restore(existing_record, related_record_data, merge)
|
114
130
|
next
|
115
131
|
end
|
116
132
|
end
|
133
|
+
# Create and restore new records
|
117
134
|
create_and_restore(associated_class, related_record_data, record, association_name)
|
118
135
|
end
|
119
136
|
end
|
120
137
|
|
138
|
+
# Restores a single association (e.g., belongs_to, has_one)
|
121
139
|
def self.restore_single_association(record, association_name, related_data, merge)
|
122
140
|
associated_class = record.class.reflect_on_association(association_name).klass
|
123
141
|
|
124
142
|
if merge && related_data['attributes']['id']
|
143
|
+
# Update existing record if merging is enabled
|
125
144
|
existing_record = record.send(association_name)
|
126
145
|
if existing_record&.id == related_data['attributes']['id']
|
127
146
|
update_and_restore(existing_record, related_data, merge)
|
@@ -129,15 +148,18 @@ module ActiveCapture
|
|
129
148
|
end
|
130
149
|
end
|
131
150
|
|
151
|
+
# Create and restore a new record
|
132
152
|
new_record = create_and_restore(associated_class, related_data)
|
133
153
|
record.update!(association_name => new_record)
|
134
154
|
end
|
135
155
|
|
156
|
+
# Updates an existing record and restores its associations
|
136
157
|
def self.update_and_restore(record, related_data, merge)
|
137
158
|
record.update!(related_data['attributes'])
|
138
159
|
restore_associations(record, related_data['associations'], merge: merge)
|
139
160
|
end
|
140
161
|
|
162
|
+
# Creates a new record and restores its associations
|
141
163
|
def self.create_and_restore(associated_class, related_data, parent_record = nil, association_name = nil)
|
142
164
|
new_record = associated_class.create!(related_data['attributes'])
|
143
165
|
restore_associations(new_record, related_data['associations'], merge: false)
|
data/lib/support/version.rb
CHANGED