views:

316

answers:

2

Does anyone know a way to determine if a Rails association has been eager loaded?

My situation: I have a result set where sometimes one of the associations is eager loaded, and sometimes it isn't. If it isn't eager-loaded, then I want to look up associations using ActiveRecord's find. If it is eager loaded, I want to use detect.

For example, say that I have a "has_many" array of shipping_info objects in my item model. Then:

If item is eager loaded, most efficient load is:

item.shipping_infos.detect { |si| si.region == "United States" }

If item isn't eager loaded, most efficient load is:

item.shipping_infos.find(:first, :conditions => { :region => "United States" })

But unless I know whether it is eager loaded, I don't know which code to call to get the record efficiently. If I use the first method when it wasn't eager loaded, then I have to look up more DB records than necessary. And if I use the second method when it was eager loaded, then my eager loaded objects are ignored.

+1  A: 

item.shipping_infos.loaded? will tell you.

(I gotta say, though: this path leads to madness... before writing code that tests loaded? to decide between #detect and #find, make sure this instance really matters, relative to everything else that's going on. If this isn't the slowest thing your app does, adding extra code paths adds unnecessary complexity. Just because you might waste a little database effort doesn't mean you need to fix it - it probably doesn't matter in any measurable way.)

Bryan Stearns
Thanks Bryan. I understand where you're coming from. This particular code happens to be in the most frequently called partial in our entire app, though, so shaving off even microseconds makes a measurable difference. I'll give #loaded? a try.
wbharding
This will only work for has_many associations! In case of belongs_to this call will actually load the other object (so it will be always true)
reto
+1  A: 

Have a look at the Bullet plugin.. This will tell you when you should and should not use eager loading.

Bitterzoet