Posted over 7 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.


Take this class:

class Activity has_many :users end

Here activity 42 has four users:

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:

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:

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

Or you can reset the association cache:

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):

# 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)
Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Arne Hartherz
Last edit:
9 months ago
by Henning Koch
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