Skip to content

MONGOID-6014: Eager load nested includes when class_name is ::-prefixed or module-relative - #6204

Open
jamis wants to merge 3 commits into
mongodb:masterfrom
jamis:MONGOID-6014-nested-includes-class-name
Open

jamis wants to merge 3 commits into
mongodb:masterfrom
jamis:MONGOID-6014-nested-includes-class-name

Conversation

@jamis

@jamis jamis commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Nested includes were being silently dropped when the parent association's class_name wasn't the resolved class name — either a "::"-prefixed string like class_name: "::Photo", or a module-relative one like class_name: "Item" inside a module. The parent association still eager-loaded, but the nested one didn't, so you'd get an N+1 with no error raised.

The cause is in preload: the work queue is matched against assoc_map keys, which are inverse_class_name values (resolved names like "Photo" or "Shop::Item"), but the queue was fed the raw class_name option. Those never matched, so the nested association was skipped entirely.

The fix pushes the resolved class name instead:

queue << (assoc.polymorphic? ? assoc.class_name : assoc.klass.name)

Polymorphic associations keep the raw class_name, since they don't resolve to a single class.

…ule-relative class_name

preload matches its work queue against assoc_map, whose keys are
inverse_class_name values (resolved class names). The queue was fed the
raw class_name option instead, so a class_name like "::Photo" or a
module-relative "Item" never matched. The nested association was then
silently skipped and loaded with one query per document.

Push the resolved class name, keeping the raw class_name only for
polymorphic associations where no single class is resolved.
@jamis
jamis requested a review from a team as a code owner October 26, 2026 22:30
@jamis
jamis requested review from comandeo-mongo and a balanced review from Copilot October 26, 2026 22:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The polymorphic guard still skips resolvable as: associations, and fixture teardown leaves temporary models registered.

2 open issues
What changed in this PR

This PR addresses silently skipped nested includes in Mongoid when an association’s class_name uses a leading :: or a module-relative name.

Changes:

  • Queues resolved target class names for non-polymorphic associations.
  • Adds regression specs checking that nested associations load without extra queries for both naming forms.
File Description
spec/​mongoid/​criteria/​includable_spec.rb Adds regression fixtures and zero-extra-query assertions.
lib/​mongoid/​association/​eager_loadable.rb Uses resolved class names when queuing nested preloads.

Review effort: Balanced

jamis added 2 commits October 27, 2026 14:26
…iations

Resolve the target class name when queuing nested preloads rather than
falling back to the raw class_name for every polymorphic association.
Parent-side `as:` associations report polymorphic? true but have a fixed,
resolvable target, so their nested includes were skipped (N+1) when the
class_name was ::-prefixed or module-relative.

Also deregister the models defined in includable_spec.rb so they no longer
leak into Mongoid.models after each context.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants