Skip to content

Commit bcd4b42

Browse files
neilshwekyp-mongo
andauthored
MONGOID-5221 Always return nil on demongoizing uncastable values (#5371)
* MONGOID-5221 DEMONGOIZE STARTS HERE: fist batch of changes * MONGOID-5221 rest of the changes * MONGOID-5221 fix extension tests * MONGOID-5221 return nil instead of raising error * MONGOID-5221 add docs and release notes * MONGOID-5221 fix some tests * MONGOID-8.0 add regexp case * MONGOID-5221 use ArgumentError instead of ::Date::Error * MONGOID-5221 add array release note * Revert "MONGOID-5221 add array release note" This reverts commit e2d1e482db201e3110ea1ad62fa4feafc41d448b. * MONGOID-5221 remove array demongoize * MONGOID-5221 fix mongoizable_spec * MONGOID-5221 update release note * MONGOID-5221 add release note * MONGOID-5221 restore documentation * MONGOID-5221 move ArgumentError * MOGNOID-5221 fix container tests * MONGOID-5221 fix tests * MONGOID-5221 add note to release notes about container demongoizers * MONGOID-5221 add note to the docs * MONGOID-5221 change range demongoize * Apply suggestions from code review Co-authored-by: Oleg Pudeyev <[email protected]> * MONGOID-5221 fix line lengths * Update docs/reference/fields.txt Co-authored-by: Oleg Pudeyev <[email protected]> * MONGOID-5221 take into account symbol keys in range * MONGOID-5221 use time with zone * MONGOID-5221 add to release notes, add tests, and remove demongoize from string * MONGOID-5221 add range as symbol keys spec * MONGOID-5221 fix rn language * MONGOID-5221 fix tests Co-authored-by: Oleg Pudeyev <[email protected]>
1 parent 723ac65 commit bcd4b42

File tree

2 files changed

+110
-23
lines changed

2 files changed

+110
-23
lines changed

source/reference/fields.txt

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -829,12 +829,20 @@ with systems that use the ``id`` field to store value different from ``_id``.
829829

830830
.. _uncastable-values:
831831

832+
Uncastable Values
833+
-----------------
834+
835+
In Mongoid 8, Mongoid has standardized the treatment of the assignment and
836+
reading of "uncastable" values. A value is considered "uncastable" when it
837+
cannot be coerced to the type of its field. For example, an array would be an
838+
"uncastable" value to an Integer field.
839+
840+
832841
Assigning Uncastable Values
833-
---------------------------
842+
```````````````````````````
834843

835-
In Mongoid 8, Mongoid has standardized the treatment of the assignment of
836-
"uncastable" values. A value is considered "uncastable" when it cannot be
837-
coerced to the type of the field. For example:
844+
The assignment of uncastable values has been standardized to assign ``nil`` by
845+
default. Consider the following example:
838846

839847
.. code::
840848

@@ -852,7 +860,7 @@ cause a ``nil`` to be written:
852860

853861
.. code::
854862

855-
user = User.new(name: [ "hello" ])
863+
user = User.new(name: [ "Mike", "Trout" ])
856864
# => #<User _id: 62b222d43282a47bf73e3264, name: nil>
857865

858866
Note that the original uncastable values will be stored in the
@@ -861,7 +869,53 @@ Note that the original uncastable values will be stored in the
861869
.. code::
862870

863871
user.attributes_before_type_cast["name"]
864-
# => ["hello"]
872+
# => ["Mike", "Trout"]
873+
874+
875+
Reading Uncastable Values
876+
`````````````````````````
877+
878+
When documents in the database contain values of different types than their
879+
represenations in Mongoid, if Mongoid cannot coerce them into the correct type,
880+
it will replace the value with ``nil``. Consider the following model and document in the
881+
database:
882+
883+
.. code::
884+
885+
class User
886+
include Mongoid::Document
887+
888+
field :name, type: Integer
889+
end
890+
891+
.. code::
892+
893+
{ _id: ..., name: [ "Mike", "Trout" ] }
894+
895+
Reading this document from the database will result in the model's name field
896+
containing ``nil``:
897+
898+
.. code::
899+
900+
User.first.name
901+
# => nil
902+
903+
The database value of type array cannot be stored in the attribute, since the
904+
array can't be coerced to an Integer. Note that the original uncastable values
905+
will be stored in the ``attributes_before_type_cast`` hash with their field
906+
names:
907+
908+
.. code::
909+
910+
user.attributes_before_type_cast["name"]
911+
# => ["Mike", "Trout"]
912+
913+
.. note::
914+
915+
The ``demongoize`` methods on container objects (i.e. Hash, Array) have not
916+
been changed to permit automatic persistence of mutated container attributes.
917+
See `MONGOID-2951 <https://jira.mongodb.org/browse/MONGOID-2951>`_ for a
918+
longer discussion of this topic.
865919

866920

867921
.. _customizing-field-behavior:
@@ -1051,12 +1105,12 @@ in the database:
10511105
.. code-block:: ruby
10521106

10531107
class ColorMapping
1054-
1108+
10551109
MAPPING = {
10561110
'black' => 0,
10571111
'white' => 1,
10581112
}.freeze
1059-
1113+
10601114
INVERSE_MAPPING = MAPPING.invert.freeze
10611115

10621116
class << self
@@ -1085,11 +1139,11 @@ in the database:
10851139
include Mongoid::Document
10861140
field :color, type: ColorMapping
10871141
end
1088-
1142+
10891143
profile = Profile.new(color: 'white')
10901144
profile.color
10911145
# => "white"
1092-
1146+
10931147
# Writes 0 to color field
10941148
profile.save!
10951149

source/release-notes/mongoid-8.0.txt

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,17 @@ changed in Mongoid 8.0:
5757
Please refer to :ref:`configuration option <configuration-options>` for
5858
the description and effects of each of these options.
5959

60-
Storing Uncastable Value
61-
------------------------
60+
Storing Uncastable Values
61+
-------------------------
6262

63-
In Mongoid 8, Mongoid standardizes the storing of "uncastable values." On
64-
attempting to write an uncastable value, a ``nil`` is written instead. See the
65-
secion on :ref:`Uncastable Values <uncastable-values>` for more details.
63+
In Mongoid 8, Mongoid standardizes the storing and reading of "uncastable
64+
values." On attempting to read or write an uncastable value, a ``nil`` is
65+
returned or written instead. See the section on
66+
:ref:`Uncastable Values <uncastable-values>` for more details.
6667

67-
Some ``mongoize`` methods were also changed to perform consistently with rails
68-
and the other mongoize methods. The following is a table of the changes in
69-
functionality:
68+
Some ``mongoize`` and ``demongoize`` methods were also changed to perform
69+
consistently with rails and the other ``mongoize`` and ``demongoize`` methods.
70+
The following is a table of the changes in functionality:
7071

7172
+--------------+------------------------+------------------------+-------------------+
7273
| Field Type | Situation | Previous Functionality | New Functionality |
@@ -75,16 +76,48 @@ functionality:
7576
| | string is assigned: | | |
7677
| | "bogus value" | | |
7778
+--------------+------------------------+------------------------+-------------------+
78-
| Array/Set | When a value that is | raise ``InvalidValue`` | return ``nil`` |
79-
| | not an array or set is | error | |
80-
| | assigned, and does NOT | | |
81-
| | respond to ``to_a``: 1 | | |
79+
| Array/Hash | When a value that is | raise ``InvalidValue`` | return ``nil`` |
80+
| | not an array or hash | error | |
81+
| | is assigned | | |
82+
+--------------+------------------------+------------------------+-------------------+
83+
| Set | When a value that is | raise ``NoMethodError``| return ``nil`` |
84+
| | not a set is assigned: | Exception: undefined | |
85+
| | 1 | method ``to_a`` for | |
86+
| | | 1:Integer | |
87+
+--------------+------------------------+------------------------+-------------------+
88+
| Regexp | When persisting and | return a | return a |
89+
| | reading a Regexp from | ``BSON::Regexp::Raw`` | ``Regexp`` |
90+
| | the database | | |
91+
+--------------+------------------------+------------------------+-------------------+
92+
| Time/DateTime| When assigning a | raise ``NoMethodError``| return ``nil`` |
93+
| | bogus value: ``:bogus``| Exception: undefined | |
94+
| | | method ``to_i`` | |
95+
| | | for :bogus:Symbol | |
96+
+--------------+------------------------+------------------------+-------------------+
97+
| Time/DateTime| When demongoizing a | raise ``NoMethodError``| "bogus": |
98+
| | non-Time value: | Exception: undefined | return ``nil`` |
99+
| | "bogus", | method ``getlocal`` | |
100+
| | ``Date.today`` | for "bogus":String | ``Date.today``: |
101+
| | | | return a |
102+
| | | | ``Time/DateTime`` |
103+
+--------------+------------------------+------------------------+-------------------+
104+
| Date | When assigning or | raise ``NoMethodError``| return ``nil`` |
105+
| | demongoizing a bogus | Exception: undefined | |
106+
| | value: :bogus | method ``year`` | |
107+
| | | for :bogus:Symbol | |
82108
+--------------+------------------------+------------------------+-------------------+
83109
| All Other | When an uncastable | undefined behavior, | return ``nil`` |
84-
| Types | value is assigned | occasionally raises | |
110+
| Types | value is assigned | occasionally raise | |
85111
| | | ``NoMethodError`` | |
86112
+--------------+------------------------+------------------------+-------------------+
87113

114+
.. note::
115+
116+
The ``demongoize`` methods on container objects (i.e. Hash, Array) have not
117+
changed to prevent bugs when modifying and saving those objects. See
118+
https://jira.mongodb.org/browse/MONGOID-2951 for a longer discussion on these
119+
bugs.
120+
88121

89122
Order of Callback Invocation
90123
----------------------------

0 commit comments

Comments
 (0)