real_data_tests 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/real_data_tests/configuration.rb +2 -1
- data/lib/real_data_tests/record_collector.rb +64 -29
- data/lib/real_data_tests/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: 21f2ee14eda8fe0a048506c0ac7948c0f1c3cacb603ddb9c6490f1abef0e7fda
|
4
|
+
data.tar.gz: '0698d429e6feb3f2dfd358014ff71b7cca4415d2393cbab950f99776191ec43c'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7839506386159938f4d5764bc0871876d7bb02ebac18ed522f23fc822e137757ea5a8a8dda7c36c4c43a91e48fa44cc0b8d69dfdca6fde402a12fe743c606fc9
|
7
|
+
data.tar.gz: bc74ab0ab3c19d1766714ebe35b25c310360a7b2d0154b675b223b46e0ee8610dd37ada15de1620867895fb922cba7edaf63a3d252e2d86dcaeb070bb9716b5b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.2] - 2025-01-14
|
4
|
+
### Fixed
|
5
|
+
- Enhanced association statistics tracking in RecordCollector
|
6
|
+
- Added separate statistics tracking method to ensure accurate counts
|
7
|
+
- Stats are now tracked before circular dependency checks
|
8
|
+
- Fixed parent-child relationship counting in recursive associations
|
9
|
+
- Improved initialization of statistics structures for better reliability
|
10
|
+
|
3
11
|
## [0.3.1] - 2025-01-14
|
4
12
|
### Fixed
|
5
13
|
- Fixed circular dependency handling in RecordCollector to correctly limit record collection
|
@@ -64,7 +64,7 @@ module RealDataTests
|
|
64
64
|
:prevent_reciprocal_loading, :anonymization_rules,
|
65
65
|
:prevented_reciprocals
|
66
66
|
|
67
|
-
attr_accessor :max_depth
|
67
|
+
attr_accessor :max_depth, :max_self_ref_depth
|
68
68
|
|
69
69
|
def initialize
|
70
70
|
@association_filter_mode = nil
|
@@ -75,6 +75,7 @@ module RealDataTests
|
|
75
75
|
@anonymization_rules = {}
|
76
76
|
@prevented_reciprocals = Set.new
|
77
77
|
@max_depth = 10
|
78
|
+
@max_self_ref_depth = 2
|
78
79
|
end
|
79
80
|
|
80
81
|
def prevent_circular_dependency(klass, association_name)
|
@@ -10,28 +10,9 @@ module RealDataTests
|
|
10
10
|
@association_path = []
|
11
11
|
@current_depth = 0
|
12
12
|
@visited_associations = {}
|
13
|
+
@processed_self_refs = Hash.new { |h, k| h[k] = Set.new }
|
13
14
|
|
14
|
-
|
15
|
-
@collection_stats[record.class.name] = {
|
16
|
-
count: 0,
|
17
|
-
associations: Hash.new(0),
|
18
|
-
polymorphic_types: {}
|
19
|
-
}
|
20
|
-
|
21
|
-
record.class.reflect_on_all_associations(:belongs_to).each do |assoc|
|
22
|
-
if assoc.polymorphic?
|
23
|
-
@collection_stats[record.class.name][:polymorphic_types][assoc.name.to_s] ||= Set.new
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
puts "\nInitializing RecordCollector for #{record.class.name}##{record.id}"
|
28
|
-
record.class.reflect_on_all_associations(:belongs_to).each do |assoc|
|
29
|
-
if assoc.polymorphic?
|
30
|
-
type = record.public_send("#{assoc.name}_type")
|
31
|
-
id = record.public_send("#{assoc.name}_id")
|
32
|
-
puts "Found polymorphic belongs_to '#{assoc.name}' with type: #{type}, id: #{id}"
|
33
|
-
end
|
34
|
-
end
|
15
|
+
init_collection_stats(record)
|
35
16
|
end
|
36
17
|
|
37
18
|
def collect
|
@@ -46,6 +27,20 @@ module RealDataTests
|
|
46
27
|
|
47
28
|
private
|
48
29
|
|
30
|
+
def init_collection_stats(record)
|
31
|
+
@collection_stats[record.class.name] = {
|
32
|
+
count: 0,
|
33
|
+
associations: Hash.new(0),
|
34
|
+
polymorphic_types: {}
|
35
|
+
}
|
36
|
+
|
37
|
+
record.class.reflect_on_all_associations(:belongs_to).each do |assoc|
|
38
|
+
if assoc.polymorphic?
|
39
|
+
@collection_stats[record.class.name][:polymorphic_types][assoc.name.to_s] ||= Set.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
49
44
|
def collect_record(record, depth)
|
50
45
|
return if @collected_records.include?(record)
|
51
46
|
return unless record # Guard against nil records
|
@@ -119,12 +114,18 @@ module RealDataTests
|
|
119
114
|
def should_process_association?(record, association, depth = 0)
|
120
115
|
return false if depth >= RealDataTests.configuration.current_preset.max_depth
|
121
116
|
|
117
|
+
# Handle self-referential associations
|
118
|
+
if self_referential_association?(record.class, association)
|
119
|
+
track_key = "#{record.class.name}:#{association.name}"
|
120
|
+
return false if @processed_self_refs[track_key].include?(record.id)
|
121
|
+
@processed_self_refs[track_key].add(record.id)
|
122
|
+
end
|
123
|
+
|
122
124
|
association_key = "#{record.class.name}##{record.id}:#{association.name}"
|
123
125
|
return false if @processed_associations.include?(association_key)
|
124
126
|
|
125
127
|
# Check if the association is allowed by configuration
|
126
128
|
should_process = RealDataTests.configuration.current_preset.should_process_association?(record, association.name)
|
127
|
-
puts " Configuration says: #{should_process}"
|
128
129
|
|
129
130
|
if should_process
|
130
131
|
@processed_associations.add(association_key)
|
@@ -138,17 +139,26 @@ module RealDataTests
|
|
138
139
|
@association_path.push(association.name)
|
139
140
|
|
140
141
|
begin
|
142
|
+
related_records = fetch_related_records(record, association)
|
143
|
+
count = related_records.length
|
144
|
+
|
145
|
+
# Track statistics even if we're going to skip processing
|
146
|
+
track_association_stats(record.class.name, association.name, count)
|
147
|
+
|
148
|
+
# Check for circular dependency after getting the related records
|
141
149
|
if detect_circular_dependency?(record, association)
|
142
150
|
puts " Skipping circular dependency for #{association.name} on #{record.class.name}##{record.id}"
|
143
151
|
return
|
144
152
|
end
|
145
153
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
154
|
+
# For self-referential associations, check depth
|
155
|
+
if self_referential_association?(record.class, association)
|
156
|
+
max_self_ref_depth = 2 # Default max depth for self-referential associations
|
157
|
+
if depth >= max_self_ref_depth
|
158
|
+
puts " Reached max self-referential depth for #{association.name}"
|
159
|
+
return
|
160
|
+
end
|
161
|
+
end
|
152
162
|
|
153
163
|
related_records.each { |related_record| collect_record(related_record, depth + 1) }
|
154
164
|
rescue => e
|
@@ -158,10 +168,30 @@ module RealDataTests
|
|
158
168
|
end
|
159
169
|
end
|
160
170
|
|
171
|
+
def track_association_stats(class_name, association_name, count)
|
172
|
+
# Initialize stats for this class if not already done
|
173
|
+
@collection_stats[class_name] ||= {
|
174
|
+
count: 0,
|
175
|
+
associations: Hash.new(0),
|
176
|
+
polymorphic_types: {}
|
177
|
+
}
|
178
|
+
|
179
|
+
# Update the association count
|
180
|
+
@collection_stats[class_name][:associations][association_name.to_s] ||= 0
|
181
|
+
@collection_stats[class_name][:associations][association_name.to_s] += count
|
182
|
+
end
|
183
|
+
|
161
184
|
def self_referential_association?(klass, association)
|
162
185
|
return false unless association.options[:class_name]
|
163
186
|
return false if association.polymorphic?
|
164
|
-
|
187
|
+
|
188
|
+
target_class_name = if association.options[:class_name].is_a?(String)
|
189
|
+
association.options[:class_name]
|
190
|
+
else
|
191
|
+
association.options[:class_name].name
|
192
|
+
end
|
193
|
+
|
194
|
+
klass.name == target_class_name
|
165
195
|
end
|
166
196
|
|
167
197
|
def detect_circular_dependency?(record, association)
|
@@ -171,6 +201,11 @@ module RealDataTests
|
|
171
201
|
target_class = association.klass
|
172
202
|
return false unless target_class
|
173
203
|
|
204
|
+
if self_referential_association?(record.class, association)
|
205
|
+
track_key = "#{target_class.name}:#{association.name}"
|
206
|
+
return @processed_self_refs[track_key].include?(record.id)
|
207
|
+
end
|
208
|
+
|
174
209
|
path_key = "#{target_class.name}:#{association.name}"
|
175
210
|
visited_count = @association_path.count { |assoc| "#{target_class.name}:#{assoc}" == path_key }
|
176
211
|
|