[LRUG] N+1

Andrew Stewart boss at airbladesoftware.com
Tue Aug 4 04:13:20 PDT 2020

Hello LRUG!

I am having trouble getting rid of database calls to read intermediate objects in a hierarchy.

I have some models like this:

    class Alpha < ApplicationRecord
      has_many :betas

    class Beta < ApplicationRecord
      belongs_to :alpha
      has_many :gammas
      has_many :deltas, through: :gammas

    class Gamma < ApplicationRecord
      belongs_to :beta
      has_many :deltas

    class Delta < ApplicationRecord
      belongs_to :gamma

And a controller action like this:

    alpha = Alpha.first
    @betas = alpha.betas
                  .joins(gammas: :deltas)  # exclude betas without deltas
                  .includes(gammas: :deltas)

And a view (pseudocode):

    - @betas.each do |beta|               # loads the @betas relation once as expected
      = beta.name
      - beta.deltas.each do |delta|       # [A] SQL query to get the beta's deltas (once per beta)
        = delta.name
        = delta.gamma.name                # [B] SQL query to get the delta's gamma (once per delta)

It seems to me I should be able to avoid the nested queries, [A] and [B], because the @betas relation includes the gammas and deltas, but I haven't succeeded yet.

Alternatively, in the console:

    beta = Beta.first
    beta.deltas.first.gamma.name  # expected 1 query; actually 2

I'm using Rails and Ruby 2.7.

Any pointers would be much appreciated!

Many thanks,

Andy Stewart

More information about the Chat mailing list