The Difference Between Joins and Includes in Rails ActiveRecord

In this article we will be explaining the difference between includes and joins in Rails ActiveRecord, a topic which often confuses newbies to Rails.

Join

Let’s look at two models, Booking and User. In the User model we have:

1
has_many :bookings

Whereas in the Booking model we have:

1
belongs_to :user

Let’s suppose we already have some data in the database and we have the following code:

1
2
3
4
bookings = Booking.where(status: completed).joins(:user)
bookings.each do |booking|
  puts booking.user.name
end

This will fire n+1 queries:

1
2
3
4
5
6
7
8
Booking Load (0.3ms)  SELECT "bookings".* FROM "bookings"
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]

Includes

The n+1 queries problem can be resolved by using includes.

1
2
3
4
5
bookings = Booking.includes(:user)
bookings.each do |booking|
  puts booking.user.name
end

This will fire only two queries:

1
2
Booking Load (4.2ms)  SELECT "bookings".* FROM "bookings"
User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2)  [["id", 1], ["id", 2]]

However, includes cannot be used in every instance. When you have to filter results from the join table, for example to get all bookings for a specific user, you cannot avoid joins.

1
2
3
4
5
bookings = Booking.joins(:user).where(email: example@email.com)

bookings.each do |booking|
  puts booking.user.name
end

Happy joining and including!