To check if an association is loaded without hitting the DB you can use:
model.association(:association_name).loaded?
for has_one
/belongs_to
associations and model.many_things.loaded?
for has_many
associations.
Checking if has_one/belongs_to association has been loaded:
user = User.find(1)
user.association(:detail).loaded? # => false
user.detail.id # Does DB request to get Detail
user.association(:detail).loaded? # => true
With Eager loading
Eager loading lets you load the data in advance, so as expected the association is marked as loaded:
user = User.eager_load(:detail).find(1)
user.detail.loaded? # => true
Checking if has_many association has been loaded
With has_many associations,
user = User.find(1)
user.association(:courses).loaded? # => false
user.courses.load # Does DB query to get all users' courses
user.association(:courses).loaded? # => true
Doing .first
or some other queries won't always load
Keep in mind that it does not mark as loaded in all cases:
user.courses.first.id # Does DB query to get first course ID
user.association(:courses).loaded? # => false (still!)
This is because it is actually doing a SELECT * LIMIT 1
query when you do the .first
for efficiency-sake.
With Eager loading
user = User.eager_load(:courses).find(1)
user.association(:courses).loaded? # => true
When to use the loaded?
method?
The only use case I can think of is when you don't want to trigger a DB call but you want to check to see if the data has been loaded already and do something with it only if it has.
In my case I wanted to output some data for logging purposes, but only if it was not adding an extra DB query by calling the association.
detail
model. This answer would query and allocate both User and Detail models. – Crunode