Careful when doing a :include with a :has_one :through association

January 12, 2009 Joseph Palermo

We had an odd bug last week where we ended up with different results after we had eager loaded an association vs loaded directly.

There are apparently two issues with :has_one :through, one of which also applies to :has_many :through.

So given:

class Person
  has_many :friendships
  has_one :best_friend, :through => :friendships, :conditions => " = 1"

If you do a Person.find(:all, :include => :best_friend), the best_friend that gets preloaded is not necessarily one that has a “ = 1”

This is due to a bug in the association preloading code that doesn’t pass down the finder options, so any :conditions or :order are completely ignored. This problem is easy to fix, just a one line change, but it then exposes another problem.

This problem applies to both :has_many :through and :has_one :through associations. The problem is that the :through association is loaded separately from the :has_one or :has_many association. So it first loads :friendships, and then when it tries to load :best_friend, it doesn’t have the table it needs for the :conditions and explodes.

Our current work around is basically putting the conditions on the :through association, although sometimes you need to create a new association just for that which is certainly not idea, especially if you plan on accessing the :through model after it has been loaded.

The way to fix it in Rails is unfortunately a rewrite of how the :through associations are eager loaded.

You can see the lighthouse ticket here

There is also a couple of messages on the Rails Core group

About the Author


More Content by Joseph Palermo
Duplicate test name detection
Duplicate test name detection

Ruby does not throw any exceptions or warnings if an object defines two methods with the same name. The se...

The Tracker Story…
The Tracker Story…

The Tracker Story... Pivotal Labs is a consulting shop and not a product company, so it might seem odd for...

Enter curious. Exit smarter.

Register Now