Preloading on instance dependent associations not working in Rails 7

Viewed 147

Support was added in Rails 7 for preloading on istance dependent associations. https://github.com/rails/rails/pull/42553

However when I upgraded my app to rails 7.0.3, running quereis on such associations that need preloading still do not work.

My models:

class Artist < ApplicationRecord
  has_many :artist_masters, ->(artist) {
    unscope(:where).where(artist_id: artist.id)
                   .or(where(composer_id: artist.id))
                   .or(where(performer_id: artist.id))
                   .or(where(conductor_id: artist.id))
  }, dependent: :destroy

  has_many :masters, through: :artist_masters
end
 
class ArtistMaster < ApplicationRecord
  belongs_to :master
  belongs_to :artist, optional: true
  belongs_to :composer, class_name: 'Artist', optional: true
  belongs_to :performer, class_name: 'Artist', optional: true
  belongs_to :conductor, class_name: 'Artist', optional: true
end 

class Master < ApplicationRecord
  has_many :artist_masters, dependent: :destroy
  has_many :artists, through: :artist_masters
  has_many :composers, class_name: 'Artist', through: :artist_masters
  has_many :performers, class_name: 'Artist', through: :artist_masters
  has_many :conductors, class_name: 'Artist', through: :artist_masters
end

When I run Artist.where.missing(:artist_masters).first I get the error:

ArgumentError: The association scope 'artist_masters' is instance dependent (the scope block takes an argument). Eager loading instance dependent scopes is not supported.
from /usr/local/bundle/gems/activerecord-7.0.3/lib/active_record/reflection.rb:500:in `check_eager_loadable!'

Would someone explain why this does not work?

1 Answers

The error here is a little obscure, but comes because missing does an eager_load and so is triggering the error because preload != eager_load, and as mentioned in the PR you cited "eager loading is still unsupported".

If you take a look at the docs for what preload is vs eager_load you'll probably be able to work out why it was feasible to add instance dependent scopes for preloading but not for eager_loading, but if not just comment back and I'll explain further.

Related