Explore the “: inverse_of” option in Rails associations

Tram Ho

Have you ever seen the option : inverse_of on a link and wondered what it did and why was it there?

The first time I saw such a thing, it seemed like an unnecessary option. So : what does inverse_of do?

Optimize memory when fetching linked records

By default, linked objects do not point to the same objects in memory. For example

When we call criminal.prison without the : inverse_of option, it will access the database. With : inverse_of , if we already have that prison in memory then crime.prison will refer to the same prison .
This saves you 1 database lookup when going from Criminal to Prison (from 1 to n in a 1-n relation). For example if going from another direction

Links in models, related to memory, are one-way constraints. : inverse_of basically gives us two-way memory constraints when one of the links is : belong_to . Memory optimization isn’t the only thing : inverse_of helps you.
Next, we will look at two use cases that involve creating related records.

Create the object and its child via accept_nested_attributes_for in the link: has_many

Suppose we have a relation as shown below and, we want to create a Prison and add more Criminals

Without : inverse_o f, this is what happens when we submit the form

When Rails saves the criminal, the prison has not been created in the database and is therefore missing id. That’s why validates :prison, presence: true return fail
For this to work, we need to have : inverse_of and the result is:

Creates has_many: through linked objects

Where you have a problem when you are creating a linked object on the other side of has_many: through . Suppose we have the relation nn declared as follows:

If we want to do something like:

Without inverse_of, we get:

Our criminal won’t have any prisons because the required sentence isn’t automatically generated.
As for inverse_of

Great, the results were what we wanted

Good news

Since version 4.1, Rail will automatically set the option : inverse_of for us. In our example above, with a Criminal linked : belongs_to to Prison , it will attempt to inverse from the class name – in this case : criminals based on the Criminal class. Surely this will be wrong when the class name does not match. For example, when we use the option : class_name or : foreign_key we have to set : inverse_of correctly, so you should still know how : inverse_of works .



Share the news now

Source : Viblo