@@ -28,17 +28,14 @@ Field type definitions determine how Mongoid behaves when constructing queries
28
28
and retrieving/writing fields from/to the database. Specifically:
29
29
30
30
1. When assigning values to fields at runtime, the values are converted to the
31
- specified type.
32
-
31
+ specified type.
33
32
2. When persisting data to MongoDB, the data is sent in an appropriate
34
- type, permitting richer data manipulation within MongoDB or by other
35
- tools.
36
-
33
+ type, permitting richer data manipulation within MongoDB or by other
34
+ tools.
37
35
3. When querying documents, query parameters are converted to the specified
38
- type before being sent to MongoDB.
39
-
36
+ type before being sent to MongoDB.
40
37
4. When retrieving documents from the database, field values are converted
41
- to the specified type.
38
+ to the specified type.
42
39
43
40
Changing the field definitions in a model class does not alter data already stored in
44
41
MongoDB. To update type or contents of fields of existing documents,
@@ -63,25 +60,26 @@ on a person by using the ``field`` macro.
63
60
The valid types for fields are as follows:
64
61
65
62
- ``Array``
66
- - ``BigDecimal``
63
+ - ``BSON::Binary``
64
+ - :ref:`BigDecimal <field-type-big-decimal>`
67
65
- ``Mongoid::Boolean``, which may be specified simply as ``Boolean`` in the
68
66
scope of a class which included ``Mongoid::Document``.
69
- - `` Date` `
70
- - `` DateTime` `
67
+ - :ref:` Date <field-type-date> `
68
+ - :ref:` DateTime <field-type-date-time> `
71
69
- ``Float``
72
- - `` Hash` `
70
+ - :ref:` Hash <field-type-hash> `
73
71
- ``Integer``
72
+ - :ref:`Object <untyped-fields>`
74
73
- ``BSON::ObjectId``
75
- - ``BSON::Binary``
76
74
- ``Range``
77
- - `` Regexp` `
75
+ - :ref:` Regexp <field-type-regexp> `
78
76
- ``Set``
79
77
- ``String``
80
- - `` Mongoid::StringifiedSymbol``, which may be specified simply as
81
- ``StringifiedSymbol`` in the scope of a class which included
82
- ``Mongoid::Document``.
83
- - `` Symbol` `
84
- - `` Time` `
78
+ - :ref:` Mongoid::StringifiedSymbol <field-type-stringified-symbol>`,
79
+ which may be specified simply as ``StringifiedSymbol`` in the scope of a
80
+ class which included ``Mongoid::Document``.
81
+ - :ref:` Symbol <field-type-stringified-symbol> `
82
+ - :ref:` Time <field-type-time> `
85
83
- ``ActiveSupport::TimeWithZone``
86
84
87
85
Mongoid also recognizes the string ``"Boolean"`` as an alias for the
@@ -97,34 +95,60 @@ To define custom field types, refer to :ref:`Custom Field Types <custom-field-ty
97
95
``BSON::Decimal128`` will return values of type ``BSON::Decimal128`` in
98
96
BSON <=4 and values of type ``BigDecimal`` in BSON 5+.
99
97
100
- .. _omitting-field-type-definition:
101
98
102
- Omitting Field Type Definition
103
- ------------------------------
99
+ .. _untyped-fields:
104
100
105
- If you decide not to specify the type of field with the definition, Mongoid will treat
106
- it as an object and not try to typecast it when sending the values to the database.
107
- This can be advantageous as the lack of attempted conversion will yield a slight
108
- performance gain. However some types are not supported if not defined as fields.
109
- You can safely omit type specifications when:
101
+ Untyped Fields
102
+ --------------
110
103
111
- - You're not using a web front end and values are already properly cast.
112
- - All of your fields are strings.
104
+ Not specifying a type for a field is the same as specifying the ``Object``
105
+ type. Such fields are untyped:
113
106
114
107
.. code-block:: ruby
115
108
116
- class Person
117
- include Mongoid::Document
118
- field :first_name
119
- field :middle_name
120
- field :last_name
121
- end
109
+ class Product
110
+ include Mongoid::Document
122
111
123
- Types that are not supported as dynamic attributes since they cannot be cast are:
112
+ field :properties
113
+ # Equivalent to:
114
+ field :properties, type: Object
115
+ end
124
116
125
- - ``Date``
126
- - ``DateTime``
127
- - ``Range``
117
+ An untyped field can store values of any type which is directly serializable
118
+ to BSON. This is useful when a field may contain values of different types
119
+ (i.e. it is a variant type field), or when the type of values is not known
120
+ ahead of time:
121
+
122
+ .. code-block:: ruby
123
+
124
+ product = Product.new(properties: "color=white,size=large")
125
+ product.properties
126
+ # => "color=white,size=large"
127
+
128
+ product = Product.new(properties: {color: "white", size: "large"})
129
+ product.properties
130
+ # => {:color=>"white", :size=>"large"}
131
+
132
+ When values are assigned to the field, Mongoid still performs mongoization but
133
+ uses the class of the value rather than the field type for mongoization logic.
134
+
135
+ .. code-block:: ruby
136
+
137
+ product = Product.new(properties: 0..10)
138
+ product.properties
139
+ # The range 0..10, mongoized:
140
+ # => {"min"=>0, "max"=>10}
141
+
142
+ When reading data from the database, Mongoid does not perform any type
143
+ conversions on untyped fields. For this reason, even though it is possible
144
+ to write any BSON-serializable value into an untyped fields, values which
145
+ require special handling on the database reading side will generally not work
146
+ correctly in an untyped field. Among field types supported by Mongoid,
147
+ values of the following types should not be stored in untyped fields:
148
+
149
+ - ``Date`` (values will be returned as ``Time``)
150
+ - ``DateTime`` (values will be returned as ``Time``)
151
+ - ``Range`` (values will be returned as ``Hash``)
128
152
129
153
130
154
.. _field-type-stringified-symbol:
@@ -447,7 +471,7 @@ matches strings containing "hello" before a newline, besides strings ending in
447
471
This is because the meaning of ``$`` is different between PCRE and Ruby
448
472
regular expressions.
449
473
450
- .. _bigdecimal-fields :
474
+ .. _field-type-big-decimal :
451
475
452
476
BigDecimal Fields
453
477
-----------------
@@ -890,6 +914,15 @@ Note that the original uncastable values will be stored in the
890
914
user.attributes_before_type_cast["name"]
891
915
# => ["Mike", "Trout"]
892
916
917
+ .. note::
918
+
919
+ Note that for numeric fields, any class that defines ``to_i`` for Integer
920
+ fields, ``to_f`` for Floats, and ``to_d`` for BigDecimals, is castable.
921
+ Strings are the exception and will only call the corresponding ``to_*``
922
+ method if the string is numeric. If a class only defines ``to_i`` and not
923
+ ``to_f`` and is being assigned to a Float field, this is uncastable, and Mongoid
924
+ will not perform a two-step conversion (i.e. ``to_i`` and then ``to_f``).
925
+
893
926
894
927
Reading Uncastable Values
895
928
`````````````````````````
@@ -1094,11 +1127,25 @@ The ``demongoize`` method is used when calling the getters of fields for your cu
1094
1127
Note that in the example above, since ``demongoize`` calls ``Point.new``, a new instance of
1095
1128
``Point`` will be generated on each call to the getter.
1096
1129
1097
- .. note::
1130
+ Mongoid will always call the ``demongoize`` method on values that were
1131
+ retrieved from the database, but applications may, in theory, call
1132
+ ``demongoize`` with arbitrary input. It is recommended that applications add
1133
+ handling for arbitrary input in their ``demongoize`` methods. We can rewrite
1134
+ ``Point``'s demongoize method as follows:
1098
1135
1099
- The ``mongoize`` and ``demongoize`` methods should return ``nil`` on values
1100
- that are uncastable to your custom type. See the section on :ref:`Uncastable
1101
- Values <uncastable-values>` for more details.
1136
+ .. code:: ruby
1137
+
1138
+ def demongoize(object)
1139
+ if object.is_a?(Array) && object.length == 2
1140
+ Point.new(object[0], object[1])
1141
+ end
1142
+ end
1143
+
1144
+ Notice that ``demongoize`` will only create a new ``Point`` if given an array
1145
+ of length 2, and will return ``nil`` otherwise. Both the ``mongoize`` and
1146
+ ``demongoize`` methods should be prepared to receive arbitrary input and should
1147
+ return ``nil`` on values that are uncastable to your custom type. See the
1148
+ section on :ref:`Uncastable Values <uncastable-values>` for more details.
1102
1149
1103
1150
Lastly, the class method ``evolve`` is similar to ``mongoize``, however it is used
1104
1151
when transforming objects for use in Mongoid query criteria.
@@ -1108,6 +1155,11 @@ when transforming objects for use in Mongoid query criteria.
1108
1155
point = Point.new(12, 24)
1109
1156
Venue.where(location: point) # This uses Point.evolve
1110
1157
1158
+ The ``evolve`` method should also be prepared to receive arbitrary input,
1159
+ however, unlike the ``mongoize`` and ``demongoize`` methods, it should return
1160
+ the inputted value on values that are uncastable to your custom type. See the
1161
+ section on :ref:`Uncastable Values <uncastable-values>` for more details.
1162
+
1111
1163
1112
1164
.. _phantom-custom-field-types:
1113
1165
@@ -1175,16 +1227,16 @@ Custom Field Options
1175
1227
You may define custom options for the ``field`` macro function
1176
1228
which extend its behavior at the your time model classes are loaded.
1177
1229
1178
- As an example, we will define a ``:required `` option which will add a presence
1230
+ As an example, we will define a ``:max_length `` option which will add a length
1179
1231
validator for the field. First, declare the new field option in an initializer,
1180
1232
specifiying its handler function as a block:
1181
1233
1182
1234
.. code-block:: ruby
1183
1235
1184
1236
# in /config/initializers/mongoid_custom_fields.rb
1185
1237
1186
- Mongoid::Fields.option :required do |model, field, value|
1187
- model.validates_presence_of field if value
1238
+ Mongoid::Fields.option :max_length do |model, field, value|
1239
+ model.validates_length_of field.name, maximum: value
1188
1240
end
1189
1241
1190
1242
Then, use it your model class:
@@ -1194,7 +1246,7 @@ Then, use it your model class:
1194
1246
class Person
1195
1247
include Mongoid::Document
1196
1248
1197
- field :name, type: String, required: true
1249
+ field :name, type: String, max_length: 10
1198
1250
end
1199
1251
1200
1252
Note that the handler function will be invoked whenever the option is used
@@ -1369,7 +1421,7 @@ Mongoid supports localized fields via `i18n <https://github.com/ruby-i18n/i18n>`
1369
1421
1370
1422
class Product
1371
1423
include Mongoid::Document
1372
- field :description, localize: true
1424
+ field :description, type: String, localize: true
1373
1425
end
1374
1426
1375
1427
By telling the field to ``localize``, Mongoid will under the covers store the field
@@ -1395,6 +1447,36 @@ You can get and set all the translations at once by using the corresponding ``_t
1395
1447
product.description_translations =
1396
1448
{ "en" => "Marvelous!", "de" => "Wunderbar!" }
1397
1449
1450
+ Localized fields can be used with any field type. For example, they can be used
1451
+ with float fields for differences with currency:
1452
+
1453
+ .. code:: ruby
1454
+
1455
+ class Product
1456
+ include Mongoid::Document
1457
+
1458
+ field :price, type: Float, localize: true
1459
+ field :currency, type: String, localize: true
1460
+ end
1461
+
1462
+ By creating the model in this way, we can separate the price from the currency
1463
+ type, which allows you to use all of the number-related functionalities on the
1464
+ price when querying or aggregating that field (provided that you index into the
1465
+ stored translations hash). We can create an instance of this model as follows:
1466
+
1467
+ .. code:: ruby
1468
+
1469
+ product = Product.new
1470
+ I18n.locale = :en
1471
+ product.price = 1.00
1472
+ product.currency = "$"
1473
+ I18n.locale = :he
1474
+ product.price = 3.24
1475
+ product.currency = "₪"
1476
+
1477
+ product.attributes
1478
+ # => { "price" => { "en" => 1.0, "he" => 3.24 }, "currency" => { "en" => "$", "he" => "₪" } }
1479
+
1398
1480
1399
1481
.. _present-fields:
1400
1482
@@ -1469,6 +1551,24 @@ language, translations will be looked up in the fallback languages:
1469
1551
I18n.locale = :de
1470
1552
product.description # "Marvelous!"
1471
1553
1554
+ Mongoid also defines a ``:fallbacks`` option on fields, which can be used to
1555
+ disable fallback functionality on a specific field:
1556
+
1557
+ .. code:: ruby
1558
+
1559
+ class Product
1560
+ include Mongoid::Document
1561
+ field :description, type: String, localize: true, fallbacks: false
1562
+ end
1563
+
1564
+ product = Product.new
1565
+ I18n.locale = :en
1566
+ product.description = "Marvelous!"
1567
+ I18n.locale = :de
1568
+ product.description # nil
1569
+
1570
+ Note that this option defaults to ``true``.
1571
+
1472
1572
.. note::
1473
1573
1474
1574
In i18n 1.1, the behavior of fallbacks `changed <https://github.com/ruby-i18n/i18n/pull/415>`_
0 commit comments