Skip to content

Ruby

Last verified end to end: 2026-07-14 (query_code schema version 2).

For exact inbound and outbound symbol edges, proof tiers, and adapter-specific caveats, see Reference Traversal.

Ruby maps ordinary and receiver calls, keyword arguments, blocks/lambdas, methods, qualified classes, assignments, and static imports. Import refinement is deliberately conservative: receiver calls named require and interpolated strings do not become precise import modules.

require "app/support"
require "plugins/#{tenant}"
module App
class Service
def run(code)
audit(code)
audit_named(code: code)
password = "hunter2"
callback = ->(value) { return value }
loader.require("plugin")
end
end
end
class App::External
end
def helper
service = App::Service.new("primary")
service.run("input")
end
missing = nil
require_relative "b"
def graph_seed
end
require_relative "c"
def graph_middle
end
def graph_target
end
require_relative "c"
def another_graph_entry
end

Pipeline wrappers transform syntax matches into declarations or files. enclosing-decl is inclusive and returns the smallest indexed declaration containing the match. file-of converts a syntax match or declaration to its exact project file.

(enclosing-decl
(language ruby (call :callee (name "audit_named"))))
{"languages":["ruby"],"match":{"kind":"call","callee":{"name":"audit_named"}},"steps":[{"op":"enclosing_decl"}]}
{
"results": [
{
"end_line": 12,
"fq_name": "App$Service.run",
"kind": "function",
"language": "ruby",
"path": "ruby/app.rb",
"provenance": [
{
"seed": {
"end_line": 8,
"kind": "call",
"path": "ruby/app.rb",
"result_type": "structural_match",
"start_line": 8
},
"steps": [
{
"op": "enclosing_decl",
"result": {
"end_line": 12,
"fq_name": "App$Service.run",
"kind": "function",
"path": "ruby/app.rb",
"result_type": "declaration",
"start_line": 6
}
}
]
}
],
"result_type": "declaration",
"signature": "(code)",
"start_line": 6
}
],
"truncated": false
}
(file-of (language ruby (function :name "graph_target")))
{"languages":["ruby"],"match":{"kind":"function","name":"graph_target"},"steps":[{"op":"file_of"}]}
{
"results": [
{
"language": "ruby",
"path": "ruby/graph/c.rb",
"provenance": [
{
"seed": {
"end_line": 2,
"kind": "function",
"path": "ruby/graph/c.rb",
"result_type": "structural_match",
"start_line": 1
},
"steps": [
{
"op": "file_of",
"result": {
"path": "ruby/graph/c.rb",
"result_type": "file"
}
}
]
}
],
"result_type": "file"
}
],
"truncated": false
}

imports-of follows one direct project-local import edge. importers-of follows the reverse direct edge; nesting it twice performs two hops rather than silently computing a transitive closure.

(imports-of
(file-of (language ruby (function :name "graph_seed"))))
{"languages":["ruby"],"match":{"kind":"function","name":"graph_seed"},"steps":[{"op":"file_of"},{"op":"imports_of"}]}
{
"results": [
{
"language": "ruby",
"path": "ruby/graph/b.rb",
"provenance": [
{
"seed": {
"end_line": 4,
"kind": "function",
"path": "ruby/graph/a.rb",
"result_type": "structural_match",
"start_line": 3
},
"steps": [
{
"op": "file_of",
"result": {
"path": "ruby/graph/a.rb",
"result_type": "file"
}
},
{
"op": "imports_of",
"result": {
"path": "ruby/graph/b.rb",
"result_type": "file"
}
}
]
}
],
"result_type": "file"
}
],
"truncated": false
}
(importers-of
(file-of (language ruby (function :name "graph_target"))))
{"languages":["ruby"],"match":{"kind":"function","name":"graph_target"},"steps":[{"op":"file_of"},{"op":"importers_of"}]}
{
"results": [
{
"language": "ruby",
"path": "ruby/graph/also_imports_c.rb",
"provenance": [
{
"seed": {
"end_line": 2,
"kind": "function",
"path": "ruby/graph/c.rb",
"result_type": "structural_match",
"start_line": 1
},
"steps": [
{
"op": "file_of",
"result": {
"path": "ruby/graph/c.rb",
"result_type": "file"
}
},
{
"op": "importers_of",
"result": {
"path": "ruby/graph/also_imports_c.rb",
"result_type": "file"
}
}
]
}
],
"result_type": "file"
},
{
"language": "ruby",
"path": "ruby/graph/b.rb",
"provenance": [
{
"seed": {
"end_line": 2,
"kind": "function",
"path": "ruby/graph/c.rb",
"result_type": "structural_match",
"start_line": 1
},
"steps": [
{
"op": "file_of",
"result": {
"path": "ruby/graph/c.rb",
"result_type": "file"
}
},
{
"op": "importers_of",
"result": {
"path": "ruby/graph/b.rb",
"result_type": "file"
}
}
]
}
],
"result_type": "file"
}
],
"truncated": false
}

This is the direct answer to “which project files import the declaration graph_target?”: first convert the declaration match to graph/c.rb, then follow one reverse edge. It returns every project file with a resolved direct import of that file; it does not claim that each importer calls graph_target, nor does it turn an external package import into a synthetic declaration.

To inspect actual uses today, run a structural call query separately. When the declaration is indexed, use scan_usages_by_reference with its exact symbol or scan_usages_by_location with its declaration range. A pipeline cannot yet feed its file results back into a second structural query as a correlated scope, so it cannot express “among these importers, find calls to this imported member” in one query.

(importers-of
(importers-of
(file-of (language ruby (function :name "graph_target")))))
{"languages":["ruby"],"match":{"kind":"function","name":"graph_target"},"steps":[{"op":"file_of"},{"op":"importers_of"},{"op":"importers_of"}]}
{
"results": [
{
"language": "ruby",
"path": "ruby/graph/a.rb",
"provenance": [
{
"seed": {
"end_line": 2,
"kind": "function",
"path": "ruby/graph/c.rb",
"result_type": "structural_match",
"start_line": 1
},
"steps": [
{
"op": "file_of",
"result": {
"path": "ruby/graph/c.rb",
"result_type": "file"
}
},
{
"op": "importers_of",
"result": {
"path": "ruby/graph/b.rb",
"result_type": "file"
}
},
{
"op": "importers_of",
"result": {
"path": "ruby/graph/a.rb",
"result_type": "file"
}
}
]
}
],
"result_type": "file"
}
],
"truncated": false
}

The keyword query selects audit_named(code: code). A receiver constraint keeps loader.require(...) as a normal call, even though bare require "..." is an import shape.

(language ruby
(call :callee (name "audit_named")
:kwargs [(code (identifier :name "code" :capture "value"))]))
{"languages":["ruby"],"match":{"kind":"call","callee":{"name":"audit_named"},"kwargs":{"code":{"kind":"identifier","name":"code","capture":"value"}}}}
{
"results": [
{
"captures": [
{"name": "value", "start_line": 8, "text": "code"}
],
"enclosing_symbol": "App$Service.run",
"end_line": 8,
"kind": "call",
"language": "ruby",
"result_type": "structural_match",
"path": "ruby/app.rb",
"start_line": 8,
"text": "audit_named(code: code)"
}
],
"truncated": false
}
(language ruby
(call :callee (name "require") :receiver (name "loader")))
{"languages":["ruby"],"match":{"kind":"call","callee":{"name":"require"},"receiver":{"name":"loader"}}}
{
"results": [
{
"enclosing_symbol": "App$Service.run",
"end_line": 11,
"kind": "call",
"language": "ruby",
"result_type": "structural_match",
"path": "ruby/app.rb",
"start_line": 11,
"text": "loader.require(\"plugin\")"
}
],
"truncated": false
}

Only fully static strings provide a module role. The interpolated plugins/#{tenant} require is intentionally absent, and the receiver call above is not classified as an import.

(language ruby (import :module (name "app/support")))
{"languages":["ruby"],"match":{"kind":"import","module":{"name":"app/support"}}}
{
"results": [
{
"end_line": 1,
"kind": "import",
"language": "ruby",
"result_type": "structural_match",
"path": "ruby/app.rb",
"start_line": 1,
"text": "require \"app/support\""
}
],
"truncated": false
}
(language ruby (import :module (name "plugins/")))
{"languages":["ruby"],"match":{"kind":"import","module":{"name":"plugins/"}}}
{
"results": [],
"truncated": false
}

has identifies the return inside the lambda. Ruby does not model decorators, so that role reports a capability diagnostic rather than a guessed match.

(language ruby (lambda :has (return)))
{"languages":["ruby"],"match":{"kind":"lambda","has":{"kind":"return"}}}
{
"results": [
{
"enclosing_symbol": "App$Service.run",
"end_line": 10,
"kind": "lambda",
"language": "ruby",
"result_type": "structural_match",
"path": "ruby/app.rb",
"start_line": 10,
"text": "->(value) { return value }"
}
],
"truncated": false
}
(language ruby (method :decorators [(name "memoized")]))
{"languages":["ruby"],"match":{"kind":"method","decorators":[{"name":"memoized"}]}}
{
"diagnostics": [
{
"language": "ruby",
"message": "structural adapter for ruby does not support role(s): decorators"
}
],
"results": [],
"truncated": false
}

Qualified declarations such as class App::External are nameable through their terminal class name, and assignments/literals remain available for ordinary Ruby data-shape queries.

(language ruby (null_literal (text/regex "^nil$")))
{"languages":["ruby"],"match":{"kind":"null_literal","text":{"regex":"^nil$"}}}
{
"results": [
{
"end_line": 24,
"kind": "null_literal",
"language": "ruby",
"result_type": "structural_match",
"path": "ruby/app.rb",
"start_line": 24,
"text": "nil"
}
],
"truncated": false
}
(language ruby (literal (text/regex "^nil$")))
{"languages":["ruby"],"match":{"kind":"literal","text":{"regex":"^nil$"}}}
{
"results": [
{
"end_line": 24,
"kind": "null_literal",
"language": "ruby",
"result_type": "structural_match",
"path": "ruby/app.rb",
"start_line": 24,
"text": "nil"
}
],
"truncated": false
}
class QueryRoot
def root_member
end
end
class QueryLeaf < QueryRoot
def leaf_member
end
end
(supertypes (enclosing-decl (language ruby (class :name "QueryLeaf"))))
{"languages":["ruby"],"match":{"kind":"class","name":"QueryLeaf"},"steps":[{"op":"enclosing_decl"},{"op":"supertypes"}]}
{
"results": [
{
"end_line": 4,
"fq_name": "QueryRoot",
"kind": "class",
"language": "ruby",
"path": "ruby/hierarchy.rb",
"provenance": [
{
"seed": {
"end_line": 9,
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "structural_match",
"start_line": 6
},
"steps": [
{
"op": "enclosing_decl",
"result": {
"end_line": 9,
"fq_name": "QueryLeaf",
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "declaration",
"start_line": 6
}
},
{
"op": "supertypes",
"result": {
"end_line": 4,
"fq_name": "QueryRoot",
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "declaration",
"start_line": 1
}
}
]
}
],
"result_type": "declaration",
"signature": "class QueryRoot",
"start_line": 1
}
],
"truncated": false
}
(owner (members (subtypes :depth 2 (enclosing-decl (language ruby (class :name "QueryRoot"))))))
{"languages":["ruby"],"match":{"kind":"class","name":"QueryRoot"},"steps":[{"op":"enclosing_decl"},{"op":"subtypes","depth":2},{"op":"members"},{"op":"owner"}]}
{
"results": [
{
"end_line": 9,
"fq_name": "QueryLeaf",
"kind": "class",
"language": "ruby",
"path": "ruby/hierarchy.rb",
"provenance": [
{
"seed": {
"end_line": 4,
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "structural_match",
"start_line": 1
},
"steps": [
{
"op": "enclosing_decl",
"result": {
"end_line": 4,
"fq_name": "QueryRoot",
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "declaration",
"start_line": 1
}
},
{
"op": "subtypes",
"result": {
"end_line": 9,
"fq_name": "QueryLeaf",
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "declaration",
"start_line": 6
}
},
{
"op": "members",
"result": {
"end_line": 8,
"fq_name": "QueryLeaf.leaf_member",
"kind": "function",
"path": "ruby/hierarchy.rb",
"result_type": "declaration",
"start_line": 7
}
},
{
"op": "owner",
"result": {
"end_line": 9,
"fq_name": "QueryLeaf",
"kind": "class",
"path": "ruby/hierarchy.rb",
"result_type": "declaration",
"start_line": 6
}
}
]
}
],
"result_type": "declaration",
"signature": "class QueryLeaf < QueryRoot",
"start_line": 6
}
],
"truncated": false
}