module ActiveRecordFollowAssoc::QueryMethods
Public Instance Methods
Query the specified association of the records that the current query would return.
Returns a new relation (also known as a query) which:
-
targets the association's model. So +Post.follow_assoc(:comments)+ will return comments.
-
only returns the records that are associated with those that the receiver would return. So +Post.where(published: true).follow_assoc(:comments)+ only returns the comments of published posts.
You could say this is a way of doing a #flat_map of the association on the result of the current relation, but without loading the records of the first relation and without having to worry about eager loading.
Examples (with equivalent #flat_map)
# Comments of published posts Post.where(published: true).follow_assoc(:comments) # Somewhat equivalent to. (Need to use preload to avoid the N+1 query problem) Post.where(published: true).preload(:comments).flat_map(:comments)
The main differences between the #flat_map and #follow_assoc approaches:
-
#follow_assocreturns a relation (or query or scope, however you call it), so you can use other scoping methods, such as#where,#limit,#order. -
#flat_mapreturns an Array, so you cannot use other scoping methods. -
#flat_mapmust be used with eager loading. Forgetting to do so makes N+1 query likely. -
#follow_assoconly loads the final matched records. -
#flat_maploads every associations on the way, this is wasteful when you don't need them.
- association_names
-
The first argument(s) are the associations that you want to follow. They are the names of your
#belongs_to,#has_many,#has_one,#has_and_belongs_to_many.If you pass in more than one, they will be followed in order. Ex: +Post.follow_assoc(:comments, :author)+ gives you the authors of the comments of the posts.
- options
-
Following are the options that can be passed as last argument.
If you are passing multiple association_names, the options only affect the last association.
- option :ignore_limit
-
When true,
#has_onewill be treated like a#has_many.Main reasons to use ignore_limit: true
-
Needed for MySQL to be able to do anything with
#has_oneassociations because MySQL doesn't support sub-limit.
See MySQL doesn’t support limit
Note, this does mean the#has_onewill be treated as if it was a#has_manyfor MySQL too. -
You have a
#has_oneassociation which you know can never have more than one record and are dealing with a heavy/slow query. The query used to deal with#has_manyis less complex, and may prove faster. -
For this one special case, you want to check the other records that match your has_one
-
- option :poly_belongs_to
-
If the last association of association_names is a polymorphic belongs_to, then by default,
#follow_assocwill raise an exception. This is because there are many unrelated models that could be the one referred to by the records, but an ActiveRecord relation can only target a single Model.For this reason, you must choose which Model to “look into” when following a polymorphic belongs_to. This is what the :poly_belongs_to option does.
For example, you can't just go from “Picture” and
follow_assocthe polymorphic belongs_to association “imageable”. But if what you are looking for is only the employees, then this works:employee_scope = pictures_scope.follow_assoc(:imageable, poly_belongs_to: Employee)
# File lib/active_record_follow_assoc/query_methods.rb, line 73 def follow_assoc(*association_names) options = association_names.extract_options! ActiveRecordFollowAssoc::CoreLogic.follow_assoc(self, association_names, options) end