Skip to content

Commit bd7c954

Browse files
committed
handle ruby hash with compact
1 parent d602372 commit bd7c954

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

src/analyze/ruby/index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ async function collectVariableAssignments(node, variableMap) {
244244
const prism = await import('@ruby/prism');
245245
const LocalVariableWriteNode = prism.LocalVariableWriteNode;
246246
const HashNode = prism.HashNode;
247+
const CallNode = prism.CallNode;
247248

248249
if (LocalVariableWriteNode && node instanceof LocalVariableWriteNode) {
249250
if (node.value instanceof HashNode) {
@@ -252,6 +253,18 @@ async function collectVariableAssignments(node, variableMap) {
252253
const { extractHashProperties } = require('./extractors');
253254
const props = await extractHashProperties(node.value);
254255
variableMap[varName] = props;
256+
} else if (node.value instanceof CallNode) {
257+
// Handle patterns like { ... }.compact or { ... }.compact!
258+
const callNode = node.value;
259+
const methodName = callNode.name;
260+
261+
// Check if the call is a compact/compact! call with a Hash receiver
262+
if ((methodName === 'compact' || methodName === 'compact!') && callNode.receiver instanceof HashNode) {
263+
const varName = node.name;
264+
const { extractHashProperties } = require('./extractors');
265+
const props = await extractHashProperties(callNode.receiver);
266+
variableMap[varName] = props;
267+
}
255268
}
256269
}
257270

tests/analyzeRuby.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,4 +392,20 @@ test.describe('analyzeRubyFile', () => {
392392
// If we get here, it means the analysis didn't hang
393393
assert.ok(true, 'Analysis completed without infinite recursion');
394394
});
395+
396+
test('should extract properties from hash assigned via .compact', async () => {
397+
const compactFile = path.join(fixturesDir, 'ruby', 'compact_event.rb');
398+
const sig = parseCustomFunctionSignature('TrackingModule.track(userId, EVENT_NAME, PROPERTIES)');
399+
const events = await analyzeRubyFile(compactFile, [sig]);
400+
assert.strictEqual(events.length, 1);
401+
402+
const evt = events[0];
403+
assert.strictEqual(evt.eventName, 'RegisteredUser');
404+
assert.deepStrictEqual(evt.properties, {
405+
userId: { type: 'number' },
406+
createdByAdminEmail: { type: 'string' },
407+
_email: { type: 'string' },
408+
emailOptIn: { type: 'boolean' }
409+
});
410+
});
395411
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
def user_registration
2+
actor_data = {
3+
createdByAdminEmail: '[email protected]',
4+
_email: '[email protected]',
5+
emailOptIn: true
6+
}.compact
7+
8+
TrackingModule.track(
9+
123,
10+
'RegisteredUser',
11+
actor_data
12+
)
13+
end

0 commit comments

Comments
 (0)