Rails strict_loading mode is to prevent lazy loading of associations.
When the strict_loading
mode is used,
the associated records will have to be eager loaded using includes
else a ActiveRecord::StrictLoadingViolationError
will be raised.
This mode helps in identifying and fixing N+1 query issues by ensuring that certain associations are loaded eagerly to avoid performance bottlenecks.
class Client < ApplicationRecord
has_many :projects
end
Client.strict_loading.first.projects
# raises ActiveRecord::StrictLoadingViolationError
class Client < ApplicationRecord
has_many :projects, strict_loading: true
end
Client.first.projects
# raises ActiveRecord::StrictLoadingViolationError
Client.includes(:projects).first.projects
Client Load (0.7ms) SELECT "clients".* FROM "clients" ORDER BY "clients"."id" ASC LIMIT $1 [["LIMIT", 1]]
Project Load (2.4ms) SELECT "projects".* FROM "projects" WHERE "projects"."client_id" = $1 [["client_id", 1]]
# =>
[#<Project:0x00000011133aaa48
id: 1,
client_id: 1,
name: "Miru",
description: "Time tracking">,
#<Project:0x0000001111f150b0
id: 2,
client_id: 1,
name: "Azure.com",
description: "Cloud Computing">
]
Before
Strict loading in :n_plus_one_only
mode is specifically designed to address performance issues that can arise when navigating through deeply nested associations
It allows direct loading of associations while restricting deeper traversal, preventing potential N+1 query issues and surprises related to ordering inconsistencies.
client = Client.find(1)
client.strict_loading!(mode: :n_plus_one_only)
client.projects.first
# SELECT "projects".* FROM "projects" WHERE "projects"."client_id" = $1 [["client_id", 1]] -- non-deterministic order
Where as navigating through deeply nested associations throws error
client.projects.first.timesheets # raises ActiveRecord::StrictLoadingViolationError
After
Strict loading using :n_plus_one_only
does not eagerly load child associations.
With this change, child associations are no longer eagerly loaded, to match intended behavior and to prevent non-deterministic order issues caused by calling methods like first or last. As first and last don’t cause an N+1 by themselves, calling child associations will no longer raise.
It means associations are eagerly loaded and child associations are lazy loaded.
client = Client.find(1)
client.strict_loading!(mode: :n_plus_one_only)
client.projects.first
# SELECT "projects".* FROM "projects" WHERE "projects"."client_id" = $1 [["client_id", 1]] -- non-deterministic order
client.projects.first.timesheets # no longer raises error
Summary
With Strict loading, we can prevent lazy loading of associations as it raises ActiveRecord::StrictLoadingViolationError
if the associated records are not eager loaded.
But With strict_loading!(mode: :n_plus_one_only)
, associations are eagerly loaded
and child associations are lazy loaded.