Skip to content

MONGOID-5936 Resolve polymorphic *_type via the association resolver in eager loader#6146

Open
comandeo-mongo wants to merge 2 commits into
mongodb:masterfrom
comandeo-mongo:MONGOID-5936-eager-polymorphic-resolver
Open

MONGOID-5936 Resolve polymorphic *_type via the association resolver in eager loader#6146
comandeo-mongo wants to merge 2 commits into
mongodb:masterfrom
comandeo-mongo:MONGOID-5936-eager-polymorphic-resolver

Conversation

@comandeo-mongo

Copy link
Copy Markdown
Contributor

MONGOID-5936

The non-eager polymorphic accessor at lib/mongoid/association/accessors.rb:43-44 goes through association.resolver.model_for(key) and raises UnrecognizedModelAlias for any value that is not registered with the configured resolver. The eager loader bypassed this and called Object.const_get(type) directly on the user-controlled *_type field at lib/mongoid/association/referenced/belongs_to/eager.rb:30. Two inconsistencies followed:

  • Apps that scope polymorphic types via a custom Mongoid::ModelResolver had no protection on the eager path. Aliases that const_get cannot resolve (e.g. "sandbox_dept") raised NameError, and any class name resolvable by const_get was loaded regardless of whether it was registered with the resolver.
  • Values that resolved to non-Document constants (e.g. "Kernel") caused a later NoMethodError instead of the documented Mongoid::Errors::UnrecognizedModelAlias.

This change routes the polymorphic type lookup through @association.resolver.model_for(type) so the eager and non-eager paths share the same allowlist and the same error contract.

Test plan

  • New spec: spec/mongoid/association/referenced/belongs_to/eager_spec.rb — eager loading raises UnrecognizedModelAlias when *_type references a constant that is not registered with the resolver.
  • New shared example in spec/integration/associations/belongs_to_spec.rb — eager loading correctly resolves alias-based *_type values across the default, registered, and unregistered resolver configurations.
  • bundle exec rubocop clean on changed files.
  • Full spec/mongoid/association/referenced/, spec/mongoid/association/eager_spec.rb, and spec/mongoid/model_resolver_spec.rb suites pass against a local replica set (3485 examples, 0 failures).

…in eager loader

The non-eager polymorphic accessor goes through `association.resolver.model_for(key)`
(`accessors.rb:43-44`), which raises `UnrecognizedModelAlias` for any value that is
not registered with the configured resolver. The eager loader bypassed this and
called `Object.const_get(type)` directly on the user-controlled `*_type` field,
producing two inconsistencies with the non-eager path:

* For applications using a custom `Mongoid::ModelResolver` to allowlist
  polymorphic types, eager loading would still resolve any constant by name,
  including aliases that `const_get` cannot find ("dept" -> NameError) and
  classes that the resolver does not allow.
* For values that resolve to non-Document constants (e.g. "Kernel"), the eager
  path would later fail with `NoMethodError` instead of the documented
  `UnrecognizedModelAlias`.

Replace `Object.const_get(type)` with `@association.resolver.model_for(type)`
so the eager and non-eager paths share the same allowlist.
@comandeo-mongo comandeo-mongo marked this pull request as ready for review June 9, 2026 08:21
@comandeo-mongo comandeo-mongo requested a review from a team as a code owner June 9, 2026 08:21
@comandeo-mongo comandeo-mongo requested review from Copilot and jamis June 9, 2026 08:21

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.

Pull request overview

This PR aligns polymorphic belongs_to eager-loading behavior with the non-eager accessor by resolving the user-controlled *_type value through the association’s configured Mongoid::ModelResolver, ensuring consistent allowlisting and error semantics.

Changes:

  • Route polymorphic eager-loader type resolution through @association.resolver.model_for(type) instead of Object.const_get(type).
  • Add a spec asserting eager loading raises Mongoid::Errors::UnrecognizedModelAlias for unregistered *_type values.
  • Add an integration spec asserting eager loading correctly resolves alias-based *_type values across resolver configurations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
lib/mongoid/association/referenced/belongs_to/eager.rb Uses the association resolver for polymorphic *_type resolution during eager loading (consistent error contract & allowlist).
spec/mongoid/association/referenced/belongs_to/eager_spec.rb Adds coverage for eager-loading raising UnrecognizedModelAlias on tampered/unregistered *_type.
spec/integration/associations/belongs_to_spec.rb Adds coverage for eager-loading resolving alternate alias values for polymorphic associations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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