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.