I have a number of custom find_by_sql queries in Rails. I would like to use eager loading with them but there doesn't seem to be a good way to do this.
I have seen the eager_custom.rb file floating around and it doesn't seem to work with Rails now. It appear Rails does eager loading differently now, using 2 queries (the regular query plus a query where the 'id IN' the ids from the first query), instead of the single join query used in the past.
My question is if I do a custom SQL query, then do 'id IN' query, is there a way to add back associated objects into the initial query results?
For example I have topics loaded with find_by_sql, then I find topic images where the topic id is in the topics ids, is there a way to add the images manually back to the topics?
Thanks
As you noticed, in Rails 2.1 a new kind of eager/pre-loading was introduced which uses multiple queries with id IN (...)
. This method is usually faster, especially when there are multiple associations being pre-loaded. You can use this functionality manually with find_by_sql
by using the preload_associations
class method inherited from ActiveRecord (not recommended). For example:
class Person
def self.find_a_special_group
people = find_by_sql("...")
preload_associations(people, [:jobs, :addresses])
return people
end
end
The preload_associations
method is protected, so you must call it from within the class, and it takes (1) an array of objects, (2) an array, hash, or symbol of associations (same format as find
's :include
option), and (3) an options hash. See the documentation for the ActiveRecord::AssociationPreload::ClassMethods module for more details.
However, having said all of that, this technique is certainly undesirable as the Rails documentation discourages programmers from using preload_associations
directly. Are you sure you have to use find_by_sql
? Are you sure you know all of the options find
takes? (:select
, :from
, :joins
, :group
, :having
, etc) I'm not saying you don't need find_by_sql
, but it might be worth a few minutes to make sure.
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