MONGOID-5892 - Treat serialize option only with values of nil and [] differently#6031
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a bug in the serializable_hash method where passing an empty array to the :only option was being treated the same as nil, causing all fields to be serialized instead of suppressing all fields as expected.
- Updates the condition to check for
nilexplicitly rather than checking if the wrapped array is empty - Adds a test case to verify that
serializable_hash(only: [])returns an empty hash
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| lib/mongoid/serializable.rb | Fixes the condition to distinguish between nil and empty array for the :only option |
| spec/mongoid/serializable_spec.rb | Adds test coverage for the empty array case |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
@bpardee -- thank you so much for this PR, we really appreciate the time you've taken to dig into Mongoid and contribute a fix. Because this PR fixes behavior that has been in place for so long (since 2012!), we're going to play it cautious, here, and move forward with the assumption that changing this behavior may potentially break existing applications. Our procedure in this case is:
We've created a ticket in Jira to track this (https://jira.mongodb.org/browse/MONGOID-5892). If you are willing to add the feature flag and corresponding specs to this PR (see Thanks again! |
…vior ofserializable_hash(only: [])
|
Ok, I'll make the changes but it seems like the values should be switched, i.e., serializable_hash_with_legacy_only == true should be the default and refer to the old behavior? |
|
Great catch @bpardee. |
|
@bpardee yes, you're correct, of course. I was typing faster than I was thinking. :) I've updated my comment to reflect the desired behavior. Thank you for updating the PR! I'll take a look at it today. |
| except |= [self.class.discriminator_key] unless Mongoid.include_type_for_serialization | ||
|
|
||
| if !only.empty? | ||
| if !options[:only].nil? && (Mongoid.serializable_hash_with_legacy_only || !only.empty?) |
There was a problem hiding this comment.
I think the logic here is reversed (probably because I misspoke when I first described the requirements).
When serializable_hash_with_legacy_only is true, this condition will be true when a non-nil value was given to :only. Thus, empty array or not, the names list will be intersected with the (possibly empty) array.
When serializable_hash_with_legacy_only is false, this condition will only be true if a non-nil, non-empty value was given to :only. Thus, only non-empty arrays will be intersected with the (possibly empty) array.
The current behavior (and the desired default behavior) is the latter case -- returning everything even if an empty array is given.
There was a problem hiding this comment.
@jamis, I fixed the logic error. Let me know if there is anything else I need to do.
jamis
left a comment
There was a problem hiding this comment.
Thank you! This looks great.
When calling serializable_hash(only: []) should suppress all fields. Currently it's treated the same as nil where it gets ignored.
Summary
Previously, passing
only: []toserializable_hashwas treated the same as passingonly: nil, meaning all fields were included. The correct behavior is to treat an empty array as "include no fields," suppressing all output.This fix is gated behind the
Mongoid.serializable_hash_with_legacy_onlyfeature flag. In 9.1 and later, the flag defaults totrue(legacy behavior); set it tofalseto opt into the new behavior. The default will flip tofalsein Mongoid 10.0, and the flag will be removed in 11.0.