Posted almost 8 years ago. Visible to the public. Repeats.

Preloaded associations are filtered by conditions on the same table

When you eagerly load an association list using the :include option, and at the same time have a :condition on an included table, two things happen:

  1. Rails 2, 3, 4, 5 tries to load all involved records in a huge single query spanning multiple database tables.
  2. The preloaded association list is filtered by the :condition, even though you only wanted to use the :condition to filter the containing model.

The second case's behavior is mostly unexpected, because pre-loaded associations usually don't care about the circumstances under which their containing model was found.

Example

Take this class:

Copy
class Activity has_many :users end

Here activity 42 has four users:

Copy
activity = Activity.find(42) activity.users.collect(&:id) # => [1, 2, 3, 4]

Let's say we want to do the same on all activities that belong to a user. To this, we scope on Activity.
Note how the activity from above now suddenly no longer contains any other users:

Copy
activity = Activity. scoped( :conditions => { :users => { :id => [4] } }, :include => :users ). find(42) activity.users.collect(&:id) # here happens the unexpected # => [4]

By reloading the object, its full list of associated users is restored:

Copy
activity.reload.users.collect(&:id) # => [1, 2, 3, 4]

Or you can reset the association cache:

Copy
activity.users.reset # newer Rails activity.users(true) # old Rails

In newer Rails versions you should prefer to use joins and then preload if necessary (which will trigger a second query):

Copy
# Join for the condition, but do not preload activities = Activity.joins(:users).where(users: { id: [4] }) # Preload associations with a second query on users; # Does not make a join. activities = activities.preload(:users)

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Owner of this card:

Avatar
Arne Hartherz
Last edit:
12 months ago
by Henning Koch
Keywords:
join, joins, has_many
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more