Mongoid 8.1#

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 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?.

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.