I am using will_paginate
with some complicated queries and it is unable to correctly calculate number of total records (in order to display proper number of page links) - namely because of grouping by multiple columns.
So, I am intending to get the SELECT query which would be used to retrieve ALL records, without actually executing it, and wrap it with SELECT COUNT(*) FROM ...
manually, in order to get the number of records.
Any ideas how to do it?
Edit: I am using Rails 2.3.x
Arel is a SQL abstraction that ActiveRecord uses to build SQL queries. Arel wraps each component of the SQL query language with Ruby objects and provides an expressive DSL for composing SQL queries. When using Arel, you're mainly interacting with tables ( Arel::Table ) and nodes ( Arel::Nodes::Node subclasses).
The Relation Class. Having queries return an ActiveRecord::Relation object allows us to chain queries together and this Relation class is at the heart of the new query syntax. Let's take a look at this class by searching through the ActiveRecord source code for a file called relation.
Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database.
For Rails 3:
Check out the ActiveRecord::Relation docs at the Rails 3 docs.
# get the relation rel = User.complex_scope.chained_complex_scope # get the SQL # this does not execute the query sql = rel.to_sql # find out how many records # this executes the query behind the scenes count = rel.size
It seems thatm in Rails 2.x, a private method called ActiveRecord::Base#construct_finder_sql
could be used, I need to test it more and see whether it will work for me:
ActionType.find(:all, :select => 'hosted, top_action_type, count(*) as count', :group => 'hosted, top_action_type').count
#=> 6
sql = ActionType.send :construct_finder_sql, :select => 'hosted, top_action_type, count(*) as count', :group => 'hosted, top_action_type'
#=> "SELECT hosted, top_action_type, count(*) as count FROM "action_types" GROUP BY hosted, top_action_type"
ActionType.count_by_sql "SELECT COUNT(*) FROM (#{sql}) a"
#=> 6
I know the question asks "without executing it", but the #explain
method is super useful and should at least be mentioned here. It is extremely useful for debugging slow queries.
Note: It does execute the query though.
http://guides.rubyonrails.org/v3.2.8/active_record_querying.html#running-explain
$ User.where("users.email LIKE '%longford%'").explain
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE (users.email LIKE '%longford%')
=> EXPLAIN for: SELECT `users`.* FROM `users` WHERE (users.email LIKE '%gmail%')
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | users | ALL | NULL | NULL | NULL | NULL | 5 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With