Mongoid 8.1
On this page
- Added
load_async
method onCriteria
to asynchronously load documents - Added
attribute_before_last_save
,saved_change_to_attribute
,saved_change_to_attribute?
, andwill_save_change_to_attribute?
methods - Deprecated
use_activesupport_time_zone
config option - Configuration DSL No Longer Requires an Argument to its Block
- Added
Mongoid::Criteria
finder methods - Added
:touch
option to#save
- Added Version Based Default Configuration
- Added
:present
option to localized fields - Added
:to
and:from
options toattribute_changed?
- Allowed
store_in
to be called on subclasses - Added
readonly!
method andlegacy_readonly
feature flag - Added method parameters to
#exists?
- Added
:replace
option to#upsert
- Allow Hash Assignment to
embedded_in
- Added
none_of
Query Method - Added
Mongoid::Config.immutable_ids
This page describes significant changes and improvements in Mongoid 8.1. The complete list of releases is available on GitHub and in JIRA; please consult GitHub releases for detailed release notes and JIRA for the complete list of issues fixed in each release, including bug fixes.
Added load_async
method on Criteria
to asynchronously load documents
The new load_async
method on Criteria
allows running database queries asynchronously.
Added attribute_before_last_save
, saved_change_to_attribute
, saved_change_to_attribute?
, and will_save_change_to_attribute?
methods
These new methods behave identically to corresponding methods
from ActiveRecord::AttributeMethods::Dirty
. The methods are particularly useful in
callbacks:
class Person include Mongoid::Document field :name, type: String before_save do puts "attribute_was(:name): #{attribute_was(:name)}" puts "attribute_before_last_save(:name): #{attribute_before_last_save(:name)}" puts "will_save_change_to_attribute?(:name): #{will_save_change_to_attribute?(:name)}" end after_save do puts "attribute_was(:name): #{attribute_was(:name)}" puts "attribute_before_last_save(:name): #{attribute_before_last_save(:name)}" puts "saved_change_to_attribute(:name): #{saved_change_to_attribute(:name)}" puts "attribute_changed?(:name): #{attribute_changed?(:name)}" puts "saved_change_to_attribute?(:name): #{saved_change_to_attribute?(:name)}" end end person = Person.create(name: 'John') # # before_save # ## attribute_was(:name): nil ## attribute_before_last_save(:name): nil ## will_save_change_to_attribute?(:name): true # # after_save # ## attribute_was(:name): John => New value ## attribute_before_last_save(:name): nil => Value before save ## saved_change_to_attribute(:name): [nil, "John"] => Both values ## attribute_changed?(:name): false ## saved_change_to_attribute?(:name): true => Correctly indicates that the change for :name was saved person.name = 'Jane' person.save # # before_save # ## attribute_was(:name): John => attribute_was not look back before the last save ## attribute_before_last_save(:name): nil => value before the last save ## will_save_change_to_attribute?(:name): true # # after_save # ## attribute_was(:name): Jane => New value ## attribute_before_last_save(:name): John => Value before save ## saved_change_to_attribute(:name): ["John", "Jane"] => Both values ## attribute_changed?(:name): false ## saved_change_to_attribute?(:name): true => Correctly indicates that the change for :name was saved
For all of the new methods there are also shorter forms created dynamically, e.g.
attribute_before_last_save(:name)
is equivalent to name_before_last_save
,
saved_change_to_attribute(:name)
is equivalent to saved_change_to_name
,
saved_change_to_attribute?(:name)
is equivalent to saved_change_to_name?
,
and will_save_change_to_attribute?(:name)
is equivalent to will_save_change_to_name?
.
Deprecated use_activesupport_time_zone
config option
The config option use_activesupport_time_zone
has been deprecated.
Beginning in Mongoid 9.0, it will be ignored and always behave as true.
Since use_activesupport_time_zone
currently defaults to true, it is
safe to remove from your config file at this time.
Configuration DSL No Longer Requires an Argument to its Block
It is now possible to use Mongoid.configure
without
providing an argument to its block:
Mongoid.configure do connect_to("mongoid_test") # Use config method when assigning variables config.preload_models = true
Note that configure
will continue to support a block argument.
The following is equivalent to the above:
Mongoid.configure do |config| config.connect_to("mongoid_test") config.preload_models = true
Added Mongoid::Criteria
finder methods
Mongoid 8.1 implements several finder methods on Mongoid::Criteria
:
first!
last!
second/second!
third/third!
fourth/fourth!
fifth/fifth!
second_to_last/second_to_last!
third_to_last/third_to_last!
When no documents are found, methods without a bang (!) return nil, and methods with a bang (!) raise an error:
Band.none.first # => nil Band.none.first! # => raise Mongoid::Errors::DocumentNotFound
Added :touch
option to #save

Support for the :touch
option has been added to the #save
and #save!
methods. When this option is false, the updated_at
field on the saved
document and all of it's embedded documents will not be updated with the
current time. When this option is true or unset, the updated_at
field will
be updated with the current time.
If the document being saved is a new document (i.e. it has not yet been
persisted to the database), then the :touch
option will be ignored, and the
updated_at
(and created_at
) fields will be updated with the current
time.
Added Version Based Default Configuration
Mongoid 8.1 has added the ability to set the default configurations for a specific version:
Mongoid.configure do |config| config.load_defaults 8.0 end
This is helpful for upgrading between versions. See the section on Version Based Default Configuration for more details on how to use this feature to make upgrading between Mongoid versions easier.
Added :present
option to localized fields
The :present
option was added to localized fields for removing blank values
from the _translations
hash:
class Product include Mongoid::Document field :description, localize: :present end
See the section on Localize :present Field Option for more details on how these are used.
Added :to
and :from
options to attribute_changed?

Mongoid 8.1 adds the :to
and :from
options on the attribute_changed?
method. These options can be used to inquire whether the attribute has been changed
to or from a certain value:
Allowed store_in
to be called on subclasses
Starting in Mongoid 8.1, subclasses can now specify which collection its
documents should be stored in using the store_in
macro:
class Shape include Mongoid::Document store_in collection: :shapes end class Circle < Shape store_in collection: :circles end class Square < Shape store_in collection: :squares end
Previously, an error was raised if this was done. See the section on Inheritance Persistence Context for more details.
Added readonly!
method and legacy_readonly
feature flag
Mongoid 8.1 changes the meaning of read-only documents. In Mongoid 8.1 with
this feature flag turned off (false
), a document becomes read-only when calling the
readonly!
method:
band = Band.first band.readonly? # => false band.readonly! band.readonly? # => true band.name = "The Rolling Stones" band.save # => raises ReadonlyDocument error
With this feature flag turned off, a ReadonlyDocument
error will be
raised when destroying or deleting, as well as when saving or updating.
Prior to Mongoid 8.1 and in 8.1 with the legacy_readonly
feature flag
turned on (true
), documents become read-only when they are projected (i.e. using
#only
or #without
).
class Band include Mongoid::Document field :name, type: String field :genre, type: String end band = Band.only(:name).first band.readonly? # => true band.destroy # => raises ReadonlyDocument error
Note that with this feature flag on, a ReadonlyDocument
error will only be
raised when destroying or deleting, and not on saving or updating. See the
section on Read-only Documents for more details.
Added method parameters to #exists?

Mongoid 8.1 introduces method paramters to the Contextual#exists?
method.
An _id, a hash of conditions, or false
/nil
can now be included:
Band.exists? Band.exists?(name: "The Rolling Stones") Band.exists?(BSON::ObjectId('6320d96a3282a48cfce9e72c')) Band.exists?(false) # always false Band.exists?(nil) # always false
Added :replace
option to #upsert

Mongoid 8.1 adds the :replace
option to the #upsert
method. This option
is false
by default.
In Mongoid 8 and earlier, and in Mongoid 8.1 when passing replace: true
(the default) the upserted document will overwrite the current document in the
database if it exists. Consider the following example:
existing = Player.create!(name: "Juan Soto", age: 23, team: "WAS") player = Player.new(name: "Juan Soto", team: "SD") player.id = existing.id player.upsert # :replace defaults to true in 8.1 p Player.find(existing.id) # => <Player _id: 633b42f43282a45fadfaaf9d, name: "Juan Soto", age: nil, team: "SD">
As you can see, the value for the :age
field was dropped, because the
upsert replaced the entire document instead of just updating it. If we take the
same example and set :replace
to false
, however:
player.upsert(replace: false) p Player.find(existing.id) # => <Player _id: 633b42f43282a45fadfaaf9d, name: "Juan Soto", age: 23, team: "SD">
This time, the value for the :age
field is maintained.
Note
The default for the :replace
option will be changed to false
in
Mongoid 9.0, therefore it is recommended to explicitly specify this option
while using #upsert
in 8.1 for easier upgradability.
Allow Hash Assignment to embedded_in

Mongoid 8.1 allows the assignment of a hash to an embedded_in
association.
On assignment, the hash will be coerced into a document of the class of the
association that it is being assigned to. This functionality already exists
for embeds_one
and embeds_many
associations. Consider the following
example:
class Band include Mongoid::Document field :name, type: String embeds_many :albums end class Album include Mongoid::Document embedded_in :band end album = Album.new album.band = { name: "Death Cab For Cutie" } p album.band # => <Band _id: 633c74113282a438a15d2b56, name: "Death Cab For Cutie">
See the section on Hash Assignment on Embedded Associations for more details
Added none_of
Query Method
With the addition of none_of
, Mongoid 8.1 allows queries to exclude
conditions in bulk. The emitted query will encapsulate the specified
criteria in a $nor
operation. For example:
class Building include Mongoid::Document field :city, type: String field :height, type: Integer field :purpose, type: String field :occupancy, type: Integer end Building.where(city: 'Portland'). none_of(:height.lt => 100, :purpose => 'apartment', :occupancy.gt => 2500)
This would query all buildings in Portland, excluding apartments, buildings less than 100 units tall, and buildings with an occupancy greater than 2500 people.
Added Mongoid::Config.immutable_ids

Coming in Mongoid 9.0, the _id
field will be immutable in both top-level
and embedded documents. This addresses some inconsistency in how mutations
to the _id
field are treated currently. To prepare for this potentially
breaking change, the Mongoid::Config.immutable_ids
flag has been added. It
defaults to false
, preserving the existing behavior, but you may set it to
true
to prepare your apps for Mongoid 9.0. When this is set to true
,
attempts to mutate the _id
of a document will raise an exception.
# The default in Mongoid 8.1 Mongoid::Config.immutable_ids = false # The default in Mongoid 9.0 Mongoid::Config.immutable_ids = true