Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Mongoid 9.1.0 raises
NoMethodErrorwhen ahas_and_belongs_to_manyassociation stores an empty foreign-key array and the association is reset before it is enumerated. Mongoid 9.0.9 does not reproduce the issue.Mongoid itself can create this data. For example,
Team.create!(user_ids: [])stores an explicit empty array.Root cause
The array-of-hashes
$lookupbranch inHasAndBelongsToMany::Buildable#buildwas added by MONGOID-5731 in pull request 6081. Because[].all? { |o| o.is_a?(Hash) }returnstrue, an empty persisted foreign-key array is treated as$lookupoutput and returned as a plain Array. After the association proxy is reset,HasMany::Enumerablehas no unloaded criteria and can call methods on a missing criteria object.Fix
The
$lookupbranch now accepts only non-empty arrays of hashes. For an empty foreign-key array, the code passesniltoquery_criteria, which returnscrit.none. This keeps the association safe to reset and lets its targetempty?,size, and enumeration methods return an empty result without querying the database, even when the general empty-$inshort-circuit option is disabled. Proxycountandexists?are outside this guarantee because they build criteria from the stored IDs.Scope
Some Array-backed targets from
$lookupcan still fail afterreset, including non-emptyhas_and_belongs_to_manyresults and emptyhas_manyresults. That issue predates this regression and is outside this change. A follow-up should hardenHasMany::Enumerablefor Array targets.Tests
The tests cover:
has_and_belongs_to_manyassociation from an empty foreign-key array returns an emptyMongoid::Criteria.Team.create!(user_ids: [])persists the empty array, and the same association proxy can be reset and used withempty?,size, and enumeration without a query.includes/preload tests cover empty eager-loaded results without an extra query.$lookupdocuments.Verification
Related Mongoid tickets
MONGOID-5030 covers short-circuiting queries whose
$invalue is an empty array. It provides related context, but it is not the same regression.