Navigation

Documents

Documents are the core objects in Mongoid and any object that is to be persisted to the database must include Mongoid::Document. The representation of a Document in MongoDB is a BSON object that is very similar to a Ruby hash or JSON object. Documents can be stored in their own collections in the database, or can be embedded in other Documents n levels deep.

Storage

Mongoid by default stores documents in a collection that is the pluralized form of the class name. For the following Person class, the collection the document would get stored in would be named people.

class Person
  include Mongoid::Document
end

Model class names cannot end with “s”, because it will be considered as the pluralized form of the word. For example “Status” would be considered as the plural form of “Statu”, which will cause a few known problems.

This is a limitation of the ActiveSupport::Inflector#classify which Mongoid uses to convert from filenames and collection names to class names. You can overcome this by specifying a custom inflection rule for your model class. For example, the following code will take care of the model named Status.

ActiveSupport::Inflector.inflections do |inflect|
  inflect.singular("status", "status")
end

The collection for the model’s documents can be changed at the class level if you would like them persisted elsewhere. You can also change the database and client the model gets persisted in from the defaults.

class Person
  include Mongoid::Document
  store_in collection: "citizens", database: "other", client: "secondary"
end

The store_in macro can also take lambdas - a common case for this is multi-tenant applications.

class Band
  include Mongoid::Document
  store_in database: ->{ Thread.current[:database] }
end

When a document is stored in the database the ruby object will get serialized into BSON and have a structure like so:

{
  "_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
  "title" : "Sir",
  "name" : {
    "_id" : ObjectId("4d3ed089fb60ab534684b7ff"),
    "first_name" : "Durran"
  },
  "addresses" : [
    {
      "_id" : ObjectId("4d3ed089fb60ab534684b7e0"),
      "city" : "Berlin",
      "country" : "Deutschland"
    }
  ]
}

Fields

Even though MongoDB is a schemaless database and allows data to be stored as strings, Mongoid permits the application to declare the type of data stored in the various fields of a document. Field type declarations affect the following:

1. When assigning values to fields, the values are converted to the specified type.

2. When persisting data to MongoDB, the data is sent in an appropriate type, permitting richer data manipulation within MongoDB or by other tools.

3. When querying documents, query parameters are converted to the specified type before being sent to MongoDB.

4. When retrieving documents from the database, field values are converted to the specified type.

Field type definitions determine how Mongoid behaves when constructing the queries, retrieving and writing fields from the database. Changing the field definitions in a model class does not alter data already stored in MongoDB. To update type or contents of fields of existing documents, the field must be re-saved to the database. Note that, due to Mongoid tracking which attributes on a model change and only saving the changed ones, it may be necessary to explicitly write a field value when changing the type of an existing field without changing the stored values.

Consider a simple class for modeling a person in an application. A person may have a first name, last name, and middle name. We can define these attributes on a person by using the field macro.

class Person
  include Mongoid::Document
  field :first_name, type: String
  field :middle_name, type: String
  field :last_name, type: String
end

Below is a list of valid types for fields.

  • Array
  • BigDecimal
  • Boolean
  • Date
  • DateTime
  • Float
  • Hash
  • Integer
  • BSON::ObjectId
  • BSON::Binary
  • Range
  • Regexp
  • Set
  • String
  • Symbol
  • Time
  • TimeWithZone

If you decide not to specify the type of field with the definition, Mongoid will treat it as an object and not try to typecast it when sending the values to the database. This can be advantageous as the lack of attempted conversion will yield a slight performance gain. However some types are not supported if not defined as fields. You can safely omit type specifications when:

  • You’re not using a web front end and values are already properly cast.
  • All of your fields are strings.
class Person
  include Mongoid::Document
  field :first_name
  field :middle_name
  field :last_name
end

Types that are not supported as dynamic attributes since they cannot be cast are:

  • BigDecimal
  • Date
  • DateTime
  • Range

Updating Container Fields

Be aware that, until MONGOID-2951 is resolved, all fields including container ones must be assigned to for their values to be persisted to the database.

For example, adding to a set like this does not work:

class Band
  include Mongoid::Document

  field :tours, type: Set
end

band = Band.new
band.tours
# => #<Set: {}>

band.tours << 'London'
# => #<Set: {"London"}>
band.tours
# => #<Set: {}>

Instead, the field value must be modified outside of the model and assigned back to the model as follows:

class Band
  include Mongoid::Document

  field :tours, type: Set
end

band = Band.new

tours = band.tours
# => #<Set: {}>

tours << 'London'
# => #<Set: {"London"}>

band.tours = tours
# => #<Set: {"London"}>

band.tours
# => #<Set: {"London"}>

Accessing Field Values

When a field is defined, Mongoid provides several different ways of accessing the field.

# Get the value of the first_name field
person.first_name
person[:first_name]
person.read_attribute(:first_name)


# Set the value for the first_name field
person.first_name = "Jean"
person[:first_name] = "Jean"
person.write_attribute(:first_name, "Jean")

You can define getters/setters that will be called when using the dot notation.

class Person
  include Mongoid::Document

  field :first_name

  # custom getter
  def first_name
    "My name is Johnny"
  end

  # custom setter
  def first_name=(value)
    p 'Setting.. '
    self.first_name = value
    p '.. done!'
  end
end

# Like this:
person.first_name = 'John'
# Setting..
# .. done!

person.first_name                  # My name is Johnny
person[:first_name]                # John
person.read_attribute(:first_name) # John

In cases where you want to set multiple field values at once, there are a few different ways of handling this as well.

# Get the field values as a hash.
person.attributes

# Set the field values in the document.
Person.new(first_name: "Jean-Baptiste", middle_name: "Emmanuel")
person.attributes = { first_name: "Jean-Baptiste", middle_name: "Emmanuel" }
person.write_attributes(
  first_name: "Jean-Baptiste",
  middle_name: "Emmanuel"
)

Hash Fields

When using a field of type Hash, be wary of adhering to the legal key names for mongoDB, or else the values will not store properly.

class Person
  include Mongoid::Document
  field :first_name
  field :url, type: Hash

  # will update the fields properly and save the values
  def set_vals
    self.first_name = 'Daniel'
    self.url = {'home_page' => 'http://www.homepage.com'}
    save
  end

  # all data will fail to save due to the illegal hashkey
  def set_vals_fail
    self.first_name = 'Daniel'
    self.url = {'home.page' => 'http://www.homepage.com'}
    save
  end
end

Date Fields

Mongoid allows assignment of values of several types to Date fields:

  • Date - the provided date is stored as is.
  • Time, DateTime, ActiveSupport::TimeWithZone - the date component of the value is taken in the value’s time zone.
  • String - the date specified in the string is used.
  • Integer, ‘’Float`` - the value is taken to be a UTC timestamp which is converted to the configured time zone (note that Mongoid.use_utc has no effect on this conversion), then the date is taken from the resulting time.

In other words, if a date is specified in the value, that date is used without first converting the value to the configured time zone.

As a date & time to date conversion is lossy (it discards the time component), especially if an application operates with times in different time zones it is recommended to explicitly convert String, Time and DateTime objects to Date objects before assigning the values to fields of type Date.

DateTime Fields

MongoDB stores all times as UTC timestamps. When assigning a value to a DateTime field, or when querying a DateTime field, Mongoid converts the passed in value to a UTC Time before sending it to the MongoDB server.

Time, ActiveSupport::TimeWithZone and DateTime objects embed time zone information, and the value persisted is the specified moment in time, in UTC. When the value is retrieved, the time zone in which it is returned is defined by the configured time zone settings.

class Ticket
  include Mongoid::Document
  field :opened_at, type: DateTime
end

Mongoid.use_activesupport_time_zone = true
Time.zone = 'Berlin'

ticket = Ticket.create!(opened_at: '2018-02-18 07:00:08 -0500')

 ticket.opened_at
 # => Sun, 18 Feb 2018 13:00:08 +0100
 ticket
 # => #<Ticket _id: 5c13d4b9026d7c4e7870bb2f, opened_at: 2018-02-18 12:00:08 UTC>

 Time.zone = 'America/New_York'
 ticket.opened_at
 # => Sun, 18 Feb 2018 07:00:08 -0500

 Mongoid.use_utc = true
 ticket.opened_at
 # => Sun, 18 Feb 2018 12:00:08 +0000

Mongoid also supports casting integers and floats to DateTime. When doing so, the integers/floats are assumed to be Unix timestamps (in UTC):

ticket.opened_at = 1544803974
ticket.opened_at
# => Fri, 14 Dec 2018 16:12:54 +0000

If a string is used as a DateTime field value, the behavior depends on whether the string includes a time zone. If no time zone is specified, the default Mongoid time zone is used:

Time.zone = 'America/New_York'
ticket.opened_at = 'Mar 4, 2018 10:00:00'
ticket.opened_at
# => Sun, 04 Mar 2018 15:00:00 +0000

If a time zone is specfied, it is respected:

ticket.opened_at = 'Mar 4, 2018 10:00:00 +01:00'
ticket.opened_at
# => Sun, 04 Mar 2018 09:00:00 +0000

Regular Expression Fields

MongoDB supports storing regular expressions in documents, and querying using regular expressions. Of note for Ruby applications, MongoDB uses Perl-compatible regular expressions (PCRE) and Ruby uses Onigmo, which is a fork of Oniguruma regular expression engine. The two regular expression implementations generally provide equivalent functionality but have some important syntax differences.

When a field is declared to be of type Regexp, Mongoid converts Ruby regular expressions to BSON regular expressions and stores the result in MongoDB. Retrieving the field from the database produces a BSON::Regexp::Raw instance:

class Token
  include Mongoid::Document

  field :pattern, type: Regexp
end

token = Token.create!(pattern: /hello.world/m)
token.pattern
# => /hello.world/m

token.reload
token.pattern
# => #<BSON::Regexp::Raw:0x0000555f505e4a20 @pattern="hello.world", @options="ms">

Use #compile method on BSON::Regexp::Raw to get back the Ruby regular expression:

token.pattern.compile
# => /hello.world/m

Note that, if the regular expression was not originally a Ruby one, calling #compile on it may produce a different regular expression. For example, the following is a PCRE matching a string that ends in “hello”:

BSON::Regexp::Raw.new('hello$', 's')
# => #<BSON::Regexp::Raw:0x0000555f51441640 @pattern="hello$", @options="s">

Compiling this regular expression produces a Ruby regular expression that matches strings containing “hello” before a newline, besides strings ending in “hello”:

BSON::Regexp::Raw.new('hello$', 's').compile =~ "hello\nworld"
# => 0

This is because the meaning of $ is different between PCRE and Ruby regular expressions.

Defaults

You can tell a field in Mongoid to always have a default value if nothing has been provided. Defaults are either static values or lambdas/procs.

class Person
  include Mongoid::Document
  field :blood_alcohol_level, type: Float, default: 0.40
  field :last_drink, type: Time, default: ->{ 10.minutes.ago }
end

Be wary that default values that are not defined as lambdas or procs are evaluated at class load time, so the following 2 definitions are not equivalent. (One would probably prefer the second, which is evaluated at document creation time.)

field :dob, type: Time, default: Time.now
field :dob, type: Time, default: ->{ Time.now }

If you want to set a default with a dependency on the document’s state, self inside a lambda or proc evaluates to the document instance.

field :intoxicated_at, type: Time, default: ->{ new_record? ? 2.hours.ago : Time.now }

When defining a default value as a proc, Mongoid will apply the default after all other attributes are set. If you want this to happen before the other attributes, set pre_processed: true.

Aliasing Fields

One of the drawbacks of having a schemaless database is that MongoDB must store all field information along with every document, meaning that it takes up a lot of storage space in RAM and on disk. A common pattern to limit this is to alias fields to a small number of characters, while keeping the domain in the application expressive. Mongoid allows you to do this and reference the fields in the domain via their long names in getters, setters, and criteria while performing the conversion for you.

class Band
  include Mongoid::Document
  field :n, as: :name, type: String
end

band = Band.new(name: "Placebo")
band.attributes # { "n" => "Placebo" }

criteria = Band.where(name: "Placebo")
criteria.selector # { "n" => "Placebo" }

Custom Fields

You can define custom types in Mongoid and determine how they are serialized and deserialized. You simply need to provide three methods on it for Mongoid to call to convert your object to and from MongoDB friendly values.

class Profile
  include Mongoid::Document
  field :location, type: Point
end

class Point

  attr_reader :x, :y

  def initialize(x, y)
    @x, @y = x, y
  end

  # Converts an object of this instance into a database friendly value.
  def mongoize
    [ x, y ]
  end

  class << self

    # Get the object as it was stored in the database, and instantiate
    # this custom class from it.
    def demongoize(object)
      Point.new(object[0], object[1])
    end

    # Takes any possible object and converts it to how it would be
    # stored in the database.
    def mongoize(object)
      case object
      when Point then object.mongoize
      when Hash then Point.new(object[:x], object[:y]).mongoize
      else object
      end
    end

    # Converts the object that was supplied to a criteria and converts it
    # into a database friendly form.
    def evolve(object)
      case object
      when Point then object.mongoize
      else object
      end
    end
  end
end

The instance method mongoize takes an instance of your object, and converts it into how it will be stored in the database. In our example above, we want to store our point object as an array in the form [ x, y ].

The class method demongoize takes an object as how it was stored in the database, and is responsible for instantiating an object of your custom type. In this case, we take an array and instantiate a Point from it.

The class method mongoize takes an object that you would use to set on your model from your application code, and create the object as it would be stored in the database. This is for cases where you are not passing your model instances of your custom type in the setter:

point = Point.new(12, 24)
venue = Venue.new(location: point) # This uses the mongoize instance method.
venue = Venue.new(location: [ 12, 24 ]) # This uses the mongoize class method.

The class method evolve takes an object, and determines how it is to be transformed for use in criteria. For example we may want to write a query like so:

point = Point.new(12, 24)
Venue.where(location: point)

Note that when accessing custom fields from the document, you will get a new instance of that object with each call to the getter. This is because Mongoid is generating a new object from the raw attributes on each access.

We need the point object in the criteria to be transformed to a Mongo friendly value when it is not as well, evolve is the method that takes care of this. We check if the passed in object is a Point first, in case we also want to be able to pass in ordinary arrays instead.

Reserved Names

Attempting to define a field on a document that conflicts with a reserved method name in Mongoid will raise an error. The list of reserved names can be obtained by invoking the Mongoid.destructive_fields method.

Field Redefinition

By default Mongoid allows redefining fields on a model. To raise an error when a field is redefined, set the duplicate_fields_exception configuration option to true.

With the option set to true, the following example will raise an error:

class Person
  include Mongoid::Document

  field :name

  field :name, type: String
end

To define the field anyway, use the overwrite: true option:

class Person
  include Mongoid::Document

  field :name

  field :name, type: String, overwrite: true
end

Custom Ids

For cases when you do not want to have BSON::ObjectId ids, you can override Mongoid’s _id field and set them to whatever you like.

class Band
  include Mongoid::Document
  field :name, type: String
  field :_id, type: String, default: ->{ name }
end

BSON Symbol Type

Because the BSON specification deprecated the BSON symbol type, the bson gem will serialize Ruby symbols into BSON strings when used on its own. However, in order to maintain backwards compatibility with older datasets, the mongo gem overrides this behavior to serialize Ruby symbols as BSON symbols. This is necessary to be able to specify queries for documents which contain BSON symbols as fields.

Although Mongoid allows applications to define fields with the Symbol type, this could present problems when using other MongoDB tools that have removed support for the type. Because of this, new applications should not specify model fields with the Symbol type but instead use the String type. Existing applications with Symbol model fields may convert those fields to Strings using one of the following methods:

  • Eager migration: Eager migration: write a script or rake task that queries each document and updates any symbols it finds to strings. This will take a long time for larger data sets, and unless the application can handle two different schemas existing in the data at once, it will need to be taken offline while the script runs.
  • Lazy migration: rather than updating all of the documents at once, each document received from a query should be reinserted if it contains a symbol; since the BSON received will have already turned the symbols into strings, this will update the document as necessary. This can be done by simply calling the save method. Note that this method will only convert documents that are accessed by the application, eventually eager migration may be needed to convert the remaining documents that haven’t been accessed.

Dynamic Fields

By default, Mongoid requires all fields that may be set on a document to be explicitly defined using field declarations. Mongoid also supports creating fields on the fly from an arbitrary hash or documents stored in the database. When a model uses fields not explicitly defined, such fields are called dynamic fields.

To enable dynamic fields, include Mongoid::Attributes::Dynamic module in the model:

class Person
  include Mongoid::Document
  include Mongoid::Attributes::Dynamic
end

bob = Person.new(name: 'Bob', age: 42)
bob.name
# => "Bob"

It is possible to use field declarations and dynamic fields in the same model class. Attributes for which there is a field declaration will be treated according to the field declaration, with remaining attributes being treated as dynamic fields.

Attribute values in the dynamic fields must initially be set by either passing the attribute hash to the constructor, mass assignment via attributes=, mass assignment via []=, using write_attribute, or they must already be present in the database.

# OK
bob = Person.new(name: 'Bob')

# OK
bob = Person.new
bob.attributes = {age: 42}

# OK
bob = Person.new
bob['age'] = 42

# Raises NoMethodError: undefined method age=
bob = Person.new
bob.age = 42

# OK
bob = Person.new
# OK - string access
bob.write_attribute('age', 42)
# OK - symbol access
bob.write_attribute(:name, 'Bob')

# OK, initializes attributes from whatever is in the database
bob = Person.find('123')

If an attribute is not present in a particular model instance’s attributes hash, both the reader and the writer for the corresponding field are not defined, and invoking them raises NoMethodError:

bob = Person.new
bob.attributes = {age: 42}

bob.age
# => 42

# raises NoMethodError
bob.name

# raises NoMethodError
bob.name = 'Bob'

# OK
bob['name'] = 'Bob'

bob.name
# => "Bob"

Attributes can always be read using mass attribute access or read_attribute (this appies to models not using dynamic fields as well):

bob = Person.new(age: 42)

# OK - string access
bob['name']
# => nil

# OK - symbol access
bob[:name]
# => nil

# OK - string access
bob['age']
# => 42

# OK - symbol access
bob[:age]
# => 42

# OK
bob.attributes['name']
# => nil

# OK
bob.attributes['age']
# => 42

# Returns nil - keys are always strings
bob.attributes[:age]
# => nil

# OK
bob.read_attribute('name')
# => nil

# OK
bob.read_attribute(:name)
# => nil

# OK - string access
bob.read_attribute('age')
# => 42

# OK - symbol access
bob.read_attribute(:age)
# => 42

Special Characters in Field Names

Mongoid permits dynamic field names to include spaces and punctuation:

bob = Person.new('hello world' => 'MDB')
bob.send('hello world')
# => "MDB"

bob.write_attribute("hello%world", 'MDB')
bob[:"hello%world"]
# => "MDB"

Localized Fields

Mongoid supports localized fields via i18n.

class Product
  include Mongoid::Document
  field :description, localize: true
end

By telling the field to localize, Mongoid will under the covers store the field as a hash of locale/value pairs, but normal access to it will behave like a string.

I18n.default_locale = :en
product = Product.new
product.description = "Marvelous!"
I18n.locale = :de
product.description = "Fantastisch!"

product.attributes
# { "description" => { "en" => "Marvelous!", "de" => "Fantastisch!" }

You can get and set all the translations at once by using the corresponding _translations method.

product.description_translations
# { "en" => "Marvelous!", "de" => "Fantastisch!" }
product.description_translations =
  { "en" => "Marvelous!", "de" => "Wunderbar!" }

Fallbacks

Mongoid integrates with i18n fallbacks. To use the fallbacks, the respective functionality must be explicitly enabled.

In a Rails application, set the config.i18n.fallbacks configuration setting to true in your environment and specify the fallback languages:

config.i18n.fallbacks = true
config.after_initialize do
  I18n.fallbacks[:de] = [ :en, :es ]
end

In a non-Rails application, include the fallbacks module into the I18n backend you are using and specify the fallback languages:

require "i18n/backend/fallbacks"
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
I18n.fallbacks[:de] = [ :en, :es ]

When fallbacks are enabled, if a translation is not present in the active language, translations will be looked up in the fallback languages:

product = Product.new
I18n.locale = :en
product.description = "Marvelous!"
I18n.locale = :de
product.description # "Marvelous!"

Note

In i18n 1.1, the behavior of fallbacks changed to always require an explicit list of fallback locales rather than falling back to the default locale when no fallback locales have been provided.

Querying

When querying for localized fields using Mongoid’s criteria API, Mongoid will automatically alter the criteria to match the current locale.

# Match all products with Marvelous as the description. Locale is en.
Product.where(description: "Marvelous!")
# The resulting MongoDB query filter: { "description.en" : "Marvelous!" }

Indexing

If you plan to be querying extensively on localized fields, you should index each of the locales that you plan on searching on.

class Product
  include Mongoid::Document
  field :description, localize: true

  index "description.de" => 1
  index "description.en" => 1
end

Dirty Tracking

Mongoid supports tracking of changed or “dirty” fields with an API that mirrors that of Active Model. If a defined field has been modified in a model the model will be marked as dirty and some additional behavior comes into play.

Viewing Changes

There are various ways to view what has been altered on a model. Changes are recorded from the time a document is instantiated, either as a new document or via loading from the database up to the time it is saved. Any persistence operation clears the changes.

class Person
  include Mongoid::Document
  field :name, type: String
end

person = Person.first
person.name = "Alan Garner"

# Check to see if the document has changed.
person.changed? # true

# Get an array of the names of the changed fields.
person.changed # [ :name ]

# Get a hash of the old and changed values for each field.
person.changes # { "name" => [ "Alan Parsons", "Alan Garner" ] }

# Check if a specific field has changed.
person.name_changed? # true

# Get the changes for a specific field.
person.name_change # [ "Alan Parsons", "Alan Garner" ]

# Get the previous value for a field.
person.name_was # "Alan Parsons"

Resetting Changes

You can reset changes of a field to its previous value by calling the reset method.

person = Person.first
person.name = "Alan Garner"

# Reset the changed name back to the original
person.reset_name!
person.name # "Alan Parsons"

Persistence

Mongoid uses dirty tracking as the core of its persistence operations. It looks at the changes on a document and atomically updates only what has changed, unlike other frameworks that write the entire document on each save. If no changes have been made, Mongoid will not hit the database on a call to Model#save.

Viewing Previous Changes

After a document has been persisted, you can see what the changes were previously by calling Model#previous_changes.

person = Person.first
person.name = "Alan Garner"
person.save # Clears out current changes.

# View the previous changes.
person.previous_changes # { "name" => [ "Alan Parsons", "Alan Garner" ] }

Read-Only Attributes

You can tell Mongoid that certain attributes are read-only. This will allow documents to be created with these attributes, but changes to them will be ignored when using mass update methods such as update_attributes:

class Band
  include Mongoid::Document
  field :name, type: String
  field :origin, type: String

  attr_readonly :name, :origin
end

band = Band.create(name: "Placebo")
band.update_attributes(name: "Tool") # Filters out the name change.

If you explicitly try to update or remove a read-only attribute by itself, a ReadonlyAttribute exception will be raised:

band.update_attribute(:name, "Tool") # Raises the error.
band.remove_attribute(:name) # Raises the error.

Inheritance

Mongoid supports inheritance in both top level and embedded documents. When a child document inherits from a parent document, the parent document’s fields, associations, validations and scopes are copied to the child document.

class Canvas
  include Mongoid::Document
  field :name, type: String
  embeds_many :shapes
end

class Browser < Canvas
  field :version, type: Integer
  scope :recent, where(:version.gt => 3)
end

class Firefox < Browser
end

class Shape
  include Mongoid::Document
  field :x, type: Integer
  field :y, type: Integer
  embedded_in :canvas
end

class Circle < Shape
  field :radius, type: Float
end

class Rectangle < Shape
  field :width, type: Float
  field :height, type: Float
end

In the above example, Canvas, Browser and Firefox will all save in the canvases collection. An additional attribute _type is stored in order to make sure when loaded from the database the correct document is returned. This also holds true for the embedded documents Circle, Rectangle, and Shape.

Querying Subclasses

Querying for subclasses is handled in the normal manner, and although the documents are all in the same collection, queries will only return documents of the correct type, similar to Single Table Inheritance in ActiveRecord.

# Returns Canvas documents and subclasses
Canvas.where(name: "Paper")
# Returns only Firefox documents
Firefox.where(name: "Window 1")

Associations

You can add any type of subclass to a has one or has many association, through either normal setting or through the build and create methods on the association:

firefox = Firefox.new
# Builds a Shape object
firefox.shapes.build({ x: 0, y: 0 })
# Builds a Circle object
firefox.shapes.build({ x: 0, y: 0 }, Circle)
# Creates a Rectangle object
firefox.shapes.create({ x: 0, y: 0 }, Rectangle)

rect = Rectangle.new(width: 100, height: 200)
firefox.shapes

Timestamping

Mongoid supplies a timestamping module in Mongoid::Timestamps which can be included to get basic behavior for created_at and updated_at fields.

class Person
  include Mongoid::Document
  include Mongoid::Timestamps
end

You may also choose to only have specific timestamps for creation or modification.

class Person
  include Mongoid::Document
  include Mongoid::Timestamps::Created
end

class Post
  include Mongoid::Document
  include Mongoid::Timestamps::Updated
end

If you want to turn off timestamping for specific calls, use the timeless method:

person.timeless.save
Person.timeless.create!

If you’d like shorter timestamp fields with aliases on them to save space, you can include the short versions of the modules.

class Band
  include Mongoid::Document
  include Mongoid::Timestamps::Short # For c_at and u_at.
end

class Band
  include Mongoid::Document
  include Mongoid::Timestamps::Created::Short # For c_at only.
end

class Band
  include Mongoid::Document
  include Mongoid::Timestamps::Updated::Short # For u_at only.
end
←   Configuration Persistence  →