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_sqlto view the final SQL string generated by Ransack without executing the query. - Inspect
Ransack::Visitorto examine how nodes inlib/ransack/nodes/condition.rband 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.rbto understand how sorts, joins, and distinct options are applied to the relation. - Call
inspecton 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →