---
title: "Rails 6.1 adds strict_loading to warn lazy loading associations"
description: "Rails 6.1 adds strict_loading to warn lazy loading associations"
canonical_url: "https://www.bigbinary.com/blog/rails-6-1-adds-strict_loading-to-warn-lazy-loading-associations"
markdown_url: "https://www.bigbinary.com/blog/rails-6-1-adds-strict_loading-to-warn-lazy-loading-associations.md"
---

# Rails 6.1 adds strict_loading to warn lazy loading associations

Rails 6.1 adds strict_loading to warn lazy loading associations

- Author: Dinesh Panda
- Published: January 6, 2021
- Categories: Rails, Rails 6.1

Rails 6.1 adds `strict_loading` mode which can be enabled per record,
association, model or across the whole application.

`strict_loading` mode is an optional setup and it helps in finding `N+1`
queries.

Let's consider the following example.

```ruby
class Article < ApplicationRecord
  has_many :comments
end

class Comment < ApplicationRecord
  belongs_to :article
end
```

#### Mark a record for strict_loading

When `strict_loading` mode is enabled for a record then its associations have to
be eager loaded otherwise Rails raises
`ActiveRecord::StrictLoadingViolationError`.

Let's see this use case by setting `strict_loading` mode for an `article`
record.

```ruby
2.7.2 :001 > article = Article.strict_loading.first
  Article Load (0.2ms)  SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<Article id: 1, title: "First article", content: "First content", created_at: "2020-12-01 07:23:38.446867000 +0000", updated_at: "2020-12-01 07:23:38.446867000 +0000">
2.7.2 :002 > article.strict_loading?
 => true
2.7.2 :003 > article.comments
Traceback (most recent call last):
ActiveRecord::StrictLoadingViolationError (`Comment` called on `Article` is marked for strict_loading and cannot be lazily loaded.)
```

`strict_loading` mode forces us to eager load the associated comments by raising
the `ActiveRecord::StrictLoadingViolationError` error.

Let's fix the `strict_loading` violation error.

```ruby
2.7.2 :004 > article = Article.includes(:comments).strict_loading.first
  Article Load (0.7ms)  SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ?  [["LIMIT", 1]]
  Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = ?  [["article_id", 1]]
 => #<Article id: 1, title: "First article", content: "First content", created_at: "2020-12-01 07:23:38.446867000 +0000", updated_at: "2020-12-01 07:23:38.446867000 +0000">
2.7.2 :005 > article.comments
 => #<ActiveRecord::Associations::CollectionProxy [#<Comment id: 1, desc: "Great article", article_id: 1, created_at: "2020-12-01 07:23:58.832869000 +0000", updated_at: "2020-12-01 07:23:58.832869000 +0000">  , #<Comment id: 2, desc: "Well written", article_id: 1, created_at: "2020-12-01 07:24:02.853376000 +0000", updated_at: "2020-12-01 07:24:02.853376000 +0000">]>
```

`strict_loading` mode on `article` record automatically sets `strict_loading`
mode for all the associated `comments` as well.

Let's verify this in Rails console.

```ruby
2.7.2 :006 > article.comments.all?(&:strict_loading?)
 => true
```

#### Mark an association for strict_loading

`strict_loading` mode can be set up for a specific association.

Let's update our example to see `strict_loading` in action when it is passed as
an option to associations.

```ruby
class Article < ApplicationRecord
  has_many :comments, strict_loading: true
end

class Comment < ApplicationRecord
  belongs_to :article
end
```

Let's verify this in Rails console.

```ruby
2.7.2 :001 > article = Article.first
  Article Load (0.2ms)  SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<Article id: 1, title: "First article", content: "First content", created_at: "2020-12-01 07:23:38.446867000 +0000", updated_at: "2020-12-01 07:23:38.446867000 +0000">
2.7.2 :002 > article.strict_loading?
 => false
2.7.2 :003 > article.comments
Traceback (most recent call last):
ActiveRecord::StrictLoadingViolationError (`comments` called on `Article` is marked for strict_loading and cannot be lazily loaded.)


2.7.2 :004 > article = Article.includes(:comments).first
  Article Load (0.2ms)  SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ?  [["LIMIT", 1]]
  Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = ?  [["article_id", 1]]
 => #<Article id: 1, title: "First article", content: "First content", created_at: "2020-12-01 07:23:38.446867000 +0000", updated_at: "2020-12-01 07:23:38.446867000 +0000">
2.7.2 :005 > article.comments
 => #<ActiveRecord::Associations::CollectionProxy [#<Comment id: 1, desc: "Great article", article_id: 1, created_at: "2020-12-01 07:23:58.832869000 +0000", updated_at: "2020-12-01 07:23:58.832869000 +0000">, #<Comment id: 2, desc: "Well written", article_id: 1, created_at: "2020-12-01 07:24:02.853376000 +0000", updated_at: "2020-12-01 07:24:02.853376000 +0000">]>
```

#### Configure strict_loading per model

We can set `strict_loading_by_default` option per model to mark all of its
records and associations for `strict_loading`.

Let's update our example to set `strict_loading_by_default` for the `Article`
model.

```ruby
class Article < ApplicationRecord
  self.strict_loading_by_default = true

  has_many :comments
end

class Comment < ApplicationRecord
  belongs_to :article
end
```

Let's verify this setting in the `Article` model.

```ruby
2.7.2 :001 > article = Article.includes(:comments).first
  Article Load (0.2ms)  SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ?  [["LIMIT", 1]]
  Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = ?  [["article_id", 1]]
 => #<Article id: 1, title: "First article", content: "First content", created_at: "2020-12-01 07:23:38.446867000 +0000", updated_at: "2020-12-01 07:23:38.446867000 +0000">
2.7.2 :002 > article.strict_loading?
 => true
2.7.2 :003 > article.comments.all?(&:strict_loading?)
 => false
2.7.2 :004 > article.comments
 => #<ActiveRecord::Associations::CollectionProxy [#<Comment id: 1, desc: "Great article", article_id: 1, created_at: "2020-12-01 07:23:58.832869000 +0000", updated_at: "2020-12-01 07:23:58.832869000 +0000">, #<Comment id: 2, desc: "Well written", article_id: 1, created_at: "2020-12-01 07:24:02.853376000 +0000", updated_at: "2020-12-01 07:24:02.853376000 +0000">]>
```

#### Make strict_loading default across all models

We can make `strict_loading` default across all models by adding the following
line to the Rails configuration file.

```ruby
config.active_record.strict_loading_by_default = true
```

---

## Configure strict_loading violations to show only in logs

By default, associations marked for strict loading always raise
`ActiveRecord::StrictLoadingViolationError` for lazy loading.

However, we may prefer to log such violations in our `production` environment
instead of raising errors.

We can add the following line to the environment configuration file.

```ruby
config.active_record.action_on_strict_loading_violation = :log
```

Check out pull requests [#37400](https://github.com/rails/rails/pull/37400),
[#38541](https://github.com/rails/rails/pull/38541),
[#39491](https://github.com/rails/rails/pull/39491) and
[#40511](https://github.com/rails/rails/pull/40511) for more details.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-6-1-adds-strict_loading-to-warn-lazy-loading-associations)
