---
title: "Rails 7 adds disable_joins for associations"
description: "Ruby 7.0 adds disable_joins for associations"
canonical_url: "https://www.bigbinary.com/blog/rails-7-adds-disable-joins-for-associations"
markdown_url: "https://www.bigbinary.com/blog/rails-7-adds-disable-joins-for-associations.md"
---

# Rails 7 adds disable_joins for associations

Ruby 7.0 adds disable_joins for associations

- Author: Ashik Salman
- Published: October 26, 2021
- Categories: Rails, Rails 7

Rails 7 introduces `disable_joins` for database associations to avoid join
errors in multi-tenant applications where the two tables are located in
different database clusters.

Rails commonly performs lazy loading while fetching records for better
efficiency and internally build join queries to fetch the records faster.

But when we deal with different database clusters within the same application,
the lazy loading nature of Active Record causes errors when the databases can't
perform join queries between different clusters.

As a resolution for this, Rails 7 has newly added 'disable_joins' option to tell
Rails upfront that queries must be performed without joining tables. In this
case two or more queries will be generated and used to fetch the results from
different database clusters.

The `disable_joins` option is available for both `has_many :through` and
`has_one :through` associations. In some cases, if order or limit is applied, it
will be performed in-memory due to database limitations.

```ruby
class Employee
  has_many :projects
  has_many :tasks, through: :projects, disable_joins: true
end

class Project
  belongs_to :employee
  has_many :tasks
end

class Task
  belongs_to :project
end
```

Before Rails 7, `@employee.tasks` without `disable_joins` option will raise
error because database clusters can't handle join queries here. If we provide
the `disable_joins` option as true (by default, the value is set to false) then
Rails will make two or more separate queries to fetch the results from different
database clusters.

```sql
SELECT "project"."id" FROM "projects" WHERE "projects"."employee_id" = ? [["employee_id", 1]]
SELECT "tasks".* FROM "tasks" WHERE "tasks"."project_id" IN (?, ?, ?) [["project_id", 1], ["project_id", 2], ["project_id", 3]]
```

Similarly, for has_one through association:

```ruby
class Publisher
  has_one :author
  has_one :book, through: :author, disable_joins: true
end

class Author
  belongs_to :publisher
  has_one :book
end

class Book
  belongs_to :author
end
```

The `@publisher.book` will make the following two queries to fetch the results.

```sql
SELECT "author"."id" FROM "authors" WHERE "authors"."publisher_id" = ? [["publisher_id", 1]]
SELECT "books".* FROM "books" WHERE "books"."author_id" = ? [["author_id", 1]]
```

Please be aware that enabling this option without realizing the actual need will
result in performance implications since two or more queries are performed here.
Also queries with order or limit will be done in-memory since the order from one
database can't be applied to another database query.

Please check out the `disable_joins` pull requests for
[has_many through](https://github.com/rails/rails/pull/41937) &
[has_one through](https://github.com/rails/rails/pull/42079) associations for
more details and discussions.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-7-adds-disable-joins-for-associations)
