Inverse Associations in Rails
Consider the following association:
class CrazyCatLady < ActiveRecord::Base
has_many :cats
end
class Cat < ActiveRecord::Base
belongs_to :crazy_cat_lady
end
Now, imagine you did:
CrazyCatLady.first.cats.first
OK, this will query the database for the first CrazyCatLady, then query again for all cats associated with that record. Fair enough. But what if we do this:
CrazyCatLady.first.cats.first.crazy_cat_lady
Aside from being a bit silly, this does everything the first statement does, then queries the database a third time to find the CrazyCatLady associated with the first cat. But Rails already has this information! Why is it querying the database again?
Rails is a bit dumb about the inverse of an association. You have to specify that an inverse relationship exists, like so:
With this done, when we issue:
CrazyCatLady.first.cats.first.crazy_cat_lady
We see that Rails won’t query the database a third time. We’ve told Rails that it already knows about the cat’s crazy_cat_lady
.
So, aside from this contrived example, how are inverse associations useful? Database queries are a precious resource in a web app. Reading and writing to disk are among the most time-intensive activities a server will perform. Too much of these activities, and a queue will start to grow. This results in slow page loads and possibly lost revenue.
Best practice in many Rails shops is to define inverse_of
on every relationship. There’s really no downside, and plenty of potential benefits.