flyerhzm / bullet

help to kill N+1 queries and unused eager loading

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

False "AVOID eager loading detected" on model association

jdufresne opened this issue · comments

Given the following schema:

ActiveRecord::Schema[7.0].define(version: 2023_01_11_023828) do
  create_table "m1_m2s", force: :cascade do |t|
    t.integer "m1_id"
    t.integer "m2_id"
  end

  create_table "m1s", force: :cascade do |t|
  end

  create_table "m2s", force: :cascade do |t|
  end

  create_table "m3s", force: :cascade do |t|
    t.integer "m1_m2_id"
  end
end

And the following model definitions:

class M1 < ApplicationRecord
  has_many :m1_m2s
end

class M2 < ApplicationRecord
end

class M1M2 < ApplicationRecord
  belongs_to :m1
  belongs_to :m2
end

class M3 < ApplicationRecord
  belongs_to :m1_m2
end

The following script results in a Bullet error:

Bullet.enable = true
Bullet.raise = true
Bullet.profile do
  m1 = M1.create!
  m2 = M2.create!
  m1_m2 = M1M2.create!(m1:, m2:)

  m3 = M3.new
  m3.m1_m2 = m1.m1_m2s.find_by!(m2:)

  puts M1M2.where(m2:).includes(:m1).index_by { |m1_m2| m1_m2.m1.id }
end

Actual

AVOID eager loading detected
  M1M2 => [:m1]
  Remove from your query: .includes([:m1])

Expected

No error.

I do not expect this error because the included m1 association is used every iteration the loop. As well, the cached m1.m1_m2s.find_by!(m2:) is not used in the loop.

Introduction

This error is new to the project. I bisected the introduction of the error to:

commit c28200313471ade03dc2081f41b8ce3b84ba70b5
Author: Adam Zapaśnik <9281806+adamzapasnik@users.noreply.github.com>
Date:   Fri Nov 25 09:27:27 2022 +0300

    Fix n+1 false positives in AR7.0

 lib/bullet/active_record70.rb                      |  7 +++++++
 spec/integration/active_record/association_spec.rb | 13 +++++++++++++
 2 files changed, 20 insertions(+)

Test project

I created a minimal test project that includes the models and script above at:

https://github.com/jdufresne/test-bullet