@@ -18,12 +18,16 @@ Field Definition
18
18
Field Types
19
19
===========
20
20
21
- Even though MongoDB is a schemaless database and allows data to be stored
22
- as strings, Mongoid permits the application to declare the type of data
23
- stored in the various fields of a document. Field type declarations affect
24
- the following:
21
+ MongoDB stores underlying document data using
22
+ `BSON types <https://docs.mongodb.com/manual/reference/bson-types/>`_, and
23
+ Mongoid converts BSON types to Ruby types at runtime in your application.
24
+ For example, a field defined with `type: :float` will use the Ruby ``Float``
25
+ class in-memory and will persist in the database as the the BSON ``double`` type.
25
26
26
- 1. When assigning values to fields, the values are converted to the
27
+ Field type definitions determine how Mongoid behaves when constructing queries
28
+ and retrieving/writing fields from/to the database. Specifically:
29
+
30
+ 1. When assigning values to fields at runtime, the values are converted to the
27
31
specified type.
28
32
29
33
2. When persisting data to MongoDB, the data is sent in an appropriate
@@ -36,26 +40,24 @@ type before being sent to MongoDB.
36
40
4. When retrieving documents from the database, field values are converted
37
41
to the specified type.
38
42
39
- Field type definitions determine how Mongoid behaves when constructing the
40
- queries, retrieving and writing fields from the database. Changing the field
41
- definitions in a model class does not alter data already stored in
43
+ Changing the field definitions in a model class does not alter data already stored in
42
44
MongoDB. To update type or contents of fields of existing documents,
43
45
the field must be re-saved to the database. Note that, due to Mongoid
44
46
tracking which attributes on a model change and only saving the changed ones,
45
47
it may be necessary to explicitly write a field value when changing the
46
48
type of an existing field without changing the stored values.
47
49
48
50
Consider a simple class for modeling a person in an application. A person may
49
- have a first name, last name , and middle name . We can define these attributes
51
+ have a name, date_of_birth , and weight . We can define these attributes
50
52
on a person by using the ``field`` macro.
51
53
52
54
.. code-block:: ruby
53
55
54
56
class Person
55
57
include Mongoid::Document
56
- field :first_name , type: String
57
- field :middle_name , type: String
58
- field :last_name , type: String
58
+ field :name , type: String
59
+ field :date_of_birth , type: Date
60
+ field :weight , type: Float
59
61
end
60
62
61
63
Below is a list of valid types for fields.
@@ -79,6 +81,14 @@ Below is a list of valid types for fields.
79
81
- ``Time``
80
82
- ``TimeWithZone``
81
83
84
+ To define custom field types, refer to :ref:`Custom Field Types <custom-field-types>` below.
85
+
86
+
87
+ .. _omitting-field-type-definition:
88
+
89
+ Omitting Field Type Definition
90
+ ------------------------------
91
+
82
92
If you decide not to specify the type of field with the definition, Mongoid will treat
83
93
it as an object and not try to typecast it when sending the values to the database.
84
94
This can be advantageous as the lack of attempted conversion will yield a slight
@@ -105,15 +115,15 @@ Types that are not supported as dynamic attributes since they cannot be cast are
105
115
- ``Range``
106
116
107
117
108
- .. _stringified -symbol:
118
+ .. _field-type-stringified -symbol:
109
119
110
- The StringifiedSymbol Type
111
- --------------------------
120
+ Field Type: StringifiedSymbol
121
+ -----------------------------
112
122
113
123
The ``StringifiedSymbol`` field type is the recommended field type for storing
114
124
values that should be exposed as symbols to Ruby applications. When using the ``Symbol`` field type,
115
125
Mongoid defaults to storing values as BSON symbols. For more information on the
116
- BSON symbol type, see :ref:`here <bson -symbol>`.
126
+ BSON symbol type, see :ref:`here <field-type -symbol>`.
117
127
However, the BSON symbol type is deprecated and is difficult to work with in programming languages
118
128
without native symbol types, so the ``StringifiedSymbol`` type allows the use of symbols
119
129
while ensuring interoperability with other drivers. The ``StringifiedSymbol`` type stores all data
@@ -159,12 +169,12 @@ migration from fields that currently store either strings or BSON symbols in the
159
169
``StringifiedSymbol`` field type.
160
170
161
171
162
- .. _bson -symbol:
172
+ .. _field-type -symbol:
163
173
164
- BSON Symbol Type
165
- ----------------
174
+ Field Type: Symbol
175
+ ------------------
166
176
167
- New applications should use the :ref:`StringifiedSymbol field type <stringified-symbol>`
177
+ New applications should use the :ref:`StringifiedSymbol field type <field-type- stringified-symbol>`
168
178
to store Ruby symbols in the database. The ``StringifiedSymbol`` field type
169
179
provides maximum compatibility with other applications and programming languages
170
180
and has the same behavior in all circumstances.
@@ -190,8 +200,10 @@ snippet in your project:
190
200
end
191
201
192
202
193
- Hash Fields
194
- -----------
203
+ .. _field-type-hash:
204
+
205
+ Field Type: Hash
206
+ ----------------
195
207
196
208
When using a field of type Hash, be wary of adhering to the
197
209
`legal key names for mongoDB <http://docs.mongodb.org/manual/reference/limits/#naming-restrictions>`_,
@@ -220,8 +232,10 @@ or else the values will not store properly.
220
232
end
221
233
222
234
223
- Time Fields
224
- -----------
235
+ .. _field-type-time:
236
+
237
+ Field Type: Time
238
+ ----------------
225
239
226
240
``Time`` fields store values as ``Time`` instances in the :ref:`configured
227
241
time zone <time-zones>`.
@@ -244,8 +258,10 @@ In the above example, the value was interpreted as the beginning of today in
244
258
local time, because the application was not configured to use UTC times.
245
259
246
260
247
- Date Fields
248
- -----------
261
+ .. _field-type-date:
262
+
263
+ Field Type: Date
264
+ ----------------
249
265
250
266
Mongoid allows assignment of values of several types to ``Date`` fields:
251
267
@@ -267,8 +283,11 @@ recommended to explicitly convert ``String``, ``Time`` and ``DateTime``
267
283
objects to ``Date`` objects before assigning the values to fields of type
268
284
``Date``.
269
285
270
- DateTime Fields
271
- ---------------
286
+
287
+ .. _field-type-date-time:
288
+
289
+ Field Type: DateTime
290
+ ---------------------
272
291
273
292
MongoDB stores all times as UTC timestamps. When assigning a value to a
274
293
``DateTime`` field, or when querying a ``DateTime`` field, Mongoid
@@ -334,13 +353,13 @@ If a time zone is specified, it is respected:
334
353
# => Sun, 04 Mar 2018 09:00:00 +0000
335
354
336
355
337
- .. _regular-expression-fields :
356
+ .. _field-type-regexp :
338
357
339
- Regular Expression Fields
340
- -------------------------
358
+ Field Type: Regexp
359
+ ------------------
341
360
342
361
MongoDB supports storing regular expressions in documents, and querying using
343
- regular expressions. Of note for Ruby applications, MongoDB uses
362
+ regular expressions. Note that MongoDB uses
344
363
`Perl-compatible regular expressions (PCRE) <http://pcre.org/>`_
345
364
and Ruby uses `Onigmo <https://github.com/k-takata/Onigmo>`_, which is a
346
365
fork of `Oniguruma regular expression engine <https://github.com/kkos/oniguruma>`_.
@@ -398,8 +417,10 @@ This is because the meaning of ``$`` is different between PCRE and Ruby
398
417
regular expressions.
399
418
400
419
401
- Defaults
402
- --------
420
+ .. _field-default-values:
421
+
422
+ Specifying Field Default Values
423
+ -------------------------------
403
424
404
425
A field can be configured to have a default value. The default value can be
405
426
fixed, as in the following example:
@@ -589,7 +610,7 @@ To define the field anyway, use the ``overwrite: true`` option:
589
610
590
611
.. _custom-id:
591
612
592
- Custom Ids
613
+ Custom IDs
593
614
----------
594
615
595
616
By default, Mongoid defines the ``_id`` field on documents to contain a
@@ -642,16 +663,20 @@ alias can :ref:`be removed <unalias-id>` if desired (such as to integrate
642
663
with systems that use the ``id`` field to store value different from ``_id``.
643
664
644
665
666
+ .. _customizing-field-behavior:
667
+
645
668
Customizing Field Behavior
646
669
==========================
647
670
648
- Mongoid offers several options for customizing the behavior of fields.
671
+ Mongoid offers several ways to customize the behavior of fields.
649
672
650
673
674
+ .. _custom-getters-and-setters:
675
+
651
676
Custom Getters And Setters
652
677
--------------------------
653
678
654
- You can define custom getters and setters for fields to modify the values
679
+ You may override getters and setters for fields to modify the values
655
680
when they are being accessed or written. The getters and setters use the
656
681
same name as the field. Use ``read_attribute`` and ``write_attribute``
657
682
methods inside the getters and setters to operate on the raw attribute
@@ -709,12 +734,14 @@ may be implemented as follows:
709
734
# => {"_id"=>BSON::ObjectId('613fa15aa15d5d617216104c'), "value"=>2.0, "unit"=>nil}
710
735
711
736
737
+ .. _custom-field-types:
738
+
712
739
Custom Field Types
713
740
------------------
714
741
715
742
You can define custom types in Mongoid and determine how they are serialized
716
- and deserialized. You simply need to provide three methods on it for Mongoid
717
- to call to convert your object to and from MongoDB friendly values.
743
+ and deserialized. In this example, we define a new field type ``Point``, which we
744
+ can use in our model class as follows:
718
745
719
746
.. code-block:: ruby
720
747
@@ -723,6 +750,11 @@ to call to convert your object to and from MongoDB friendly values.
723
750
field :location, type: Point
724
751
end
725
752
753
+ Then make a Ruby class to represent the type. This class must define methods
754
+ used for MongoDB serialization and deserialization as follows:
755
+
756
+ .. code-block:: ruby
757
+
726
758
class Point
727
759
728
760
attr_reader :x, :y
@@ -732,18 +764,13 @@ to call to convert your object to and from MongoDB friendly values.
732
764
end
733
765
734
766
# Converts an object of this instance into a database friendly value.
767
+ # In this example, we store the values in the database as array.
735
768
def mongoize
736
769
[ x, y ]
737
770
end
738
771
739
772
class << self
740
773
741
- # Get the object as it was stored in the database, and instantiate
742
- # this custom class from it.
743
- def demongoize(object)
744
- Point.new(object[0], object[1])
745
- end
746
-
747
774
# Takes any possible object and converts it to how it would be
748
775
# stored in the database.
749
776
def mongoize(object)
@@ -754,8 +781,14 @@ to call to convert your object to and from MongoDB friendly values.
754
781
end
755
782
end
756
783
784
+ # Get the object as it was stored in the database, and instantiate
785
+ # this custom class from it.
786
+ def demongoize(object)
787
+ Point.new(object[0], object[1])
788
+ end
789
+
757
790
# Converts the object that was supplied to a criteria and converts it
758
- # into a database friendly form.
791
+ # into a query- friendly form.
759
792
def evolve(object)
760
793
case object
761
794
when Point then object.mongoize
@@ -765,42 +798,69 @@ to call to convert your object to and from MongoDB friendly values.
765
798
end
766
799
end
767
800
768
- The instance method ``mongoize`` takes an instance of your object, and
769
- converts it into how it will be stored in the database. In our example above,
770
- we want to store our point object as an array in the form ``[ x, y ]``.
801
+ The instance method ``mongoize`` takes an instance of your custom type object, and
802
+ converts it into a represenation of how it will be stored in the database, i.e. to pass
803
+ to the MongoDB Ruby driver. In our example above, we want to store our ``Point``
804
+ object as an ``Array`` in the form ``[ x, y ]``.
771
805
772
- The class method ``demongoize`` takes an object as how it was stored in the
773
- database, and is responsible for instantiating an object of your custom type.
774
- In this case, we take an array and instantiate a ``Point`` from it.
775
-
776
- The class method ``mongoize`` takes an object that you would use to set on
777
- your model from your application code, and create the object as it would be
778
- stored in the database. This is for cases where you are not passing your
779
- model instances of your custom type in the setter:
806
+ The class method ``mongoize`` is similar to the instance method, however it must handle
807
+ objects of all possible types as inputs. The ``mongoize`` method is used when calling the
808
+ setter methods for fields of your custom type.
780
809
781
810
.. code-block:: ruby
782
811
783
812
point = Point.new(12, 24)
784
- venue = Venue.new(location: point) # This uses the mongoize instance method.
785
- venue = Venue.new(location: [ 12, 24 ]) # This uses the mongoize class method.
813
+ venue = Venue.new(location: point) # This uses the Point#mongoize instance method.
814
+ venue = Venue.new(location: [ 12, 24 ]) # This uses the Point.mongoize class method.
815
+
816
+ The class method ``demongoize`` does the inverse of ``mongoize``. It takes the raw object
817
+ from the MongoDB Ruby driver and converts it to an instance of your custom type.
818
+ In this case, the database driver returns an ``Array`` and we instantiate a ``Point`` from it.
819
+ The ``demongoize`` method is used when calling the getters of fields for your custom type.
820
+ Note that in the example above, since ``demongoize`` calls ``Point.new``, a new instance of
821
+ ``Point`` will be generated on each call to the getter.
786
822
787
- The class method ``evolve`` takes an object, and determines how it is to be
788
- transformed for use in criteria. For example we may want to write a query
789
- like so:
823
+ Lastly, the class method ``evolve`` is similar to ``mongoize``, however it is used
824
+ when transforming objects for use in Mongoid query criteria.
790
825
791
826
.. code-block:: ruby
792
827
793
828
point = Point.new(12, 24)
794
- Venue.where(location: point)
829
+ Venue.where(location: point) # This uses Point.evolve
830
+
831
+
832
+ .. _custom-field-options:
833
+
834
+ Custom Field Options
835
+ --------------------
795
836
796
- Note that when accessing custom fields from the document, you will get a
797
- new instance of that object with each call to the getter. This is because
798
- Mongoid is generating a new object from the raw attributes on each access.
837
+ You may define custom options for the ``field`` macro function
838
+ which extend its behavior at the your time model classes are loaded.
839
+
840
+ As an example, we will define a ``:required`` option which will add a presence
841
+ validator for the field. First, declare the new field option in an initializer,
842
+ specifiying its handler function as a block:
843
+
844
+ .. code-block:: ruby
845
+
846
+ # in /config/initializers/mongoid_custom_fields.rb
847
+
848
+ Mongoid::Fields.option :required do |model, field, value|
849
+ model.validates_presence_of field if value
850
+ end
851
+
852
+ Then, use it your model class:
853
+
854
+ .. code-block:: ruby
855
+
856
+ class Person
857
+ include Mongoid::Document
858
+
859
+ field :name, type: String, required: true
860
+ end
799
861
800
- We need the point object in the criteria to be transformed to a
801
- MongoDB-friendly value when it is not as well, ``evolve`` is the method
802
- that takes care of this. We check if the passed in object is a ``Point``
803
- first, in case we also want to be able to pass in ordinary arrays instead.
862
+ Note that the handler function will be invoked whenever the option is used
863
+ in the field definition, even if the option's value is false or nil.
804
864
805
865
806
866
.. _dynamic-fields:
0 commit comments