superJustin
superJustin

Reputation: 65

Eager Load Active Record Association with WHERE on Join Clause

I'd like to perform an eager load but have a where clause on the eager load query.

Let's say we have the following:

class Features < ActiveRecord::Base
  has_many :feature_overrides
end

class FeatureOverride < ActiveRecord::Base
  belongs_to :feature
end

Where a feature has an active attribute, which can be overridden by a feature override.

Feature overrides are added for users, so the active attribute on a feature can be overridden by a feature override for a particular user.

Here's the query I have to get all features and eager load the feature_overrides:

Features.all.includes(:feature_overrides)

With this query I'd still have to search the feature_overrides to see if there exists a feature override for a given user. Adding a where to the eager load doesn't give me what I want:

Features.all.includes(:feature_overrides).where('feature_overrides.username = ?', username)

This will reduce my result to only include features where there exists an override for username.

At this point I think what I want is to do a Left Outer Join, but when I try that active record does not deserialize the feature override association.

I'd like the eager load to somehow perform the queries:

SELECT `features`.* FROM `features`
SELECT `feature_overrides`.* FROM `feature_overrides` WHERE `feature_overrides`.`feature_id` IN (...) AND `feature_overrides`.`username` = ?

Upvotes: 0

Views: 517

Answers (1)

Psylone
Psylone

Reputation: 2808

So that's sound like you need the Left Outer Join (exactly what you wrote in the question, but my mind was blinded). If you're on Rails 5 try to use this:

Feature.left_outer_joins(:feature_overrides)

If you're on Rails 4 you will need to write this one manually:

Feature.joins(%[LEFT OUTER JOIN 'feature_overrides' ON 'feature_overrides'.'feature_id' = 'features'.'id'])

You can also append where scope if you need to filter feature_overrides by the username.

Upvotes: 0

Related Questions