How to Debug and Inspect the SQL Queries Generated by Ransack

Call search.result.to_sql on any Ransack search object to view the raw SQL, or inspect the Arel tree directly via Ransack::Visitor to debug how predicates are constructed before execution.

The Ransack gem provides advanced search capabilities for Rails applications by translating HTTP parameters into database queries. When you need to debug and inspect the SQL queries generated by Ransack, you must understand how the library constructs queries through its node-based architecture before handing them off to ActiveRecord. By examining specific source files in the activerecord-hackery/ransack repository, you can trace exactly how search parameters become executable SQL.

Understanding Ransack's Query Building Pipeline

Ransack constructs queries in three distinct phases implemented across core library files. First, Ransack::Search in lib/ransack/search.rb parses input parameters into a tree of nodes including Ransack::Nodes::Condition, Ransack::Nodes::Grouping, and Ransack::Nodes::Sort. Second, the Ransack::Visitor class defined in lib/ransack/visitor.rb traverses these nodes and converts them into Arel predicates through methods like visit_Ransack_Nodes_Condition. Finally, the ActiveRecord context in lib/ransack/adapters/active_record/context.rb evaluates the search via the evaluate method, applying the Arel tree to the base relation and handling sorts at line 30 before returning a standard ActiveRecord::Relation.

Because the final output is an ActiveRecord relation, all standard Rails SQL inspection methods remain available.

Inspecting SQL with ActiveRecord Methods

Once Ransack returns a relation object, you can leverage Rails native debugging tools to view the generated SQL.

Using to_sql on the Result Relation

The simplest approach to debug and inspect the SQL queries generated by Ransack involves calling to_sql on the result relation. In lib/ransack/search.rb, the result method delegates to @context.evaluate(self, opts), which returns an ActiveRecord::Relation compatible with standard query methods.


# In Rails console or controller

search = Article.ransack(title_cont: 'Rails', published_eq: true)
sql = search.result.to_sql

puts sql

# => SELECT "articles".* FROM "articles" 

#    WHERE "articles"."title" ILIKE '%Rails%' AND "articles"."published" = 't'

Inspecting the Search Object Tree

To examine the internal node structure before SQL generation, use the inspect method on the search object. This reveals the Ransack::Nodes::Grouping hierarchy that the visitor will traverse.

search = Comment.ransack(body_cont: 'spam')
puts search.inspect

# => Ransack::Search<ActiveRecord::Base, base: #<Ransack::Nodes::Grouping ...>>

Debugging the Arel Tree Directly

For deeper debugging, you can intercept the Arel objects before they reach ActiveRecord. The visitor pattern in lib/ransack/visitor.rb accepts the search base and returns Arel-compatible nodes.

search = User.ransack(name_start: 'A', age_gt: 30)

# Inspect raw Arel before it joins the relation

arel = Ransack::Visitor.new.accept(search.base)
puts arel.to_sql

# => ("users"."name" LIKE 'A%' AND "users"."age" > 30)

This approach is particularly useful when verifying that custom predicates in lib/ransack/nodes/condition.rb are generating valid arel_predicate objects.

Enabling SQL Logging in Rails

Configure Rails to log all queries, including those generated by Ransack's context evaluation in lib/ransack/adapters/active_record/context.rb. Set the log level to debug and enable verbose query logs in your environment configuration.


# config/environments/development.rb

Rails.application.configure do
  config.log_level = :debug
  config.active_record.verbose_query_logs = true
end

After configuration, executing a search will output the SQL to your logs:

Article.ransack(title_cont: 'Rails').result.load

# Article Load (0.5ms)  SELECT "articles".* FROM "articles" 

# ↳ WHERE "articles"."title" ILIKE '%Rails%'

Debugging Complex Queries and Sorts

When debugging scope-based sorting, note that Ransack treats sort strings matching defined scopes as symbols. The context applies these in the sort-handling loop beginning at line 30 of lib/ransack/adapters/active_record/context.rb.


# Assuming Post model has a :most_recent scope

search = Post.ransack(s: 'most_recent desc')
relation = search.result

# Verify the scope application and ordering

puts relation.to_sql

This is critical when joins are involved, as the context also manages association handling and join building between lines 26-65 of the same file.

Summary

  • Use search.result.to_sql to view the final SQL string generated by Ransack without executing the query.
  • Inspect Ransack::Visitor to examine how nodes in lib/ransack/nodes/condition.rb and related files convert to Arel predicates.
  • Enable Rails debug logging to capture SQL output in development logs via config.active_record.verbose_query_logs.
  • Check lib/ransack/adapters/active_record/context.rb to understand how sorts, joins, and distinct options are applied to the relation.
  • Call inspect on the search object to view the raw node tree before visitor processing.

Frequently Asked Questions

How do I see the SQL without executing the query?

Call to_sql on the result relation. Because search.result returns an ActiveRecord::Relation from lib/ransack/adapters/active_record/context.rb, you can invoke search.result.to_sql to generate the SQL string without hitting the database.

Where does Ransack convert search parameters to SQL?

The conversion happens in two stages. First, lib/ransack/visitor.rb transforms node objects into Arel predicates. Second, lib/ransack/adapters/active_record/context.rb evaluates these predicates against the base relation via the evaluate method, producing the final SQL.

Can I debug Ransack queries in production?

Yes, but use caution. You can temporarily enable debug logging or use to_sql in production consoles, but avoid verbose logging permanently due to performance overhead. For persistent debugging, use the Visitor approach to inspect Arel objects without executing queries.

How do I inspect scope-based sorts in Ransack?

When a sort parameter matches a model scope, Ransack delegates to that scope in the sort-handling loop of lib/ransack/adapters/active_record/context.rb. Verify the SQL by calling to_sql on the result, or check if the scope appears in the relation's order values via search.result.order_values.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →