real_data_tests 0.3.1 → 0.3.2
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 +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
|
|