Callbacks
On this page
Overview
In this guide, you can learn how to implement callbacks in your Mongoid models to customize the life cycle of your model instances.
Callbacks are methods that Mongoid triggers at specified moments of an object's life cycle. They allow you to initiate specified actions before or after changes to an object's state.
Mongoid implements many of the callbacks from Active Record. To learn more, see Callbacks in the Active Record documentation.
Supported Callbacks
Mongoid supports the following callbacks on model classes that implement the Document module:
after_initialize
after_build
before_validation
after_validation
before_create
around_create
after_create
after_find
before_update
around_update
after_update
before_upsert
around_upsert
after_upsert
before_save
around_save
after_save
before_destroy
around_destroy
after_destroy
To learn more about any of the preceding callback types, see the ActiveRecord::Callbacks reference in the Rails API documentation.
You can implement callbacks in both top-level and embedded document models.
Note
Callback Invocation Behavior
For efficiency, Mongoid invokes the callback only on the document that you performed the persistence action on. This behavior enables Mongoid to support large hierarchies and handle optimized atomic updates efficiently by not invoking callbacks throughout the document hierarchy.
Take precautions and ensure testability when implementing callbacks for domain logic, because these designs can lead to unexpected errors when callbacks in the chain halt execution. We recommend using callbacks for cross-cutting concerns outside of your program's core functionality, such as queueing up background jobs.
Document Callbacks
You must implement and register callbacks on your model classes.
You can register a callback by using ordinary methods, blocks and
Proc
objects, or by defining custom callback objects that use
classes or modules.
This example demonstrates how to register callbacks on the Contact
model class in the following ways:
Includes the
before_save
class method, which triggers theprocess_phone
method before aContact
instance is saved to MongoDB. Theprocess_phone
method is defined separately in the class.Includes the
after_destroy
class method and uses a block to print a message when aContact
instance is deleted.
class Contact include Mongoid::Document field :name, type: String field :phone, type: String # Creates a callback to clean phone numbers before saving before_save :process_phone protected def process_phone self.phone = phone.gsub(/[^0-9]/, "") if attribute_present?("phone") end # Creates a callback to send a message about object deletion after_destroy do p "deleted the contact for #{name}" end end
The following code performs data operations that demonstrate the callback actions:
Contact.create(name: 'Serena Atherton', phone: '999 555-3030') # => `phone` field saved as '9995553030' Contact.create(name: 'Zayba Haq', phone: '999 123?5050') # => `phone` field saved as '9991235050' Contact.first.destroy # => Console message: "deleted the contact for Serena Atherton"
Because callback functionality comes from Active Support, you can
alternatively use the set_callback
class method syntax to register
callbacks. The following code demonstrates how to use this syntax to
create a callback that stores original values of the name
field in
the aliases
array:
class Contact include Mongoid::Document field :name, type: String field :phone, type: String field :aliases, type: Array, default: [] set_callback(:update, :before) do |document| if document.name_changed? document.push(aliases: document.name_was) end end end Contact.create(name: 'Xavier Bloom', phone: '4447779999') Contact.first.update(name: 'Xav - coworker') # Saved document in MongoDB: # {"aliases":["Xavier Bloom"],"name":"Xav - coworker","phone":"4447779999"}
Association Callbacks
Mongoid provides the following association callbacks:
after_add
after_remove
before_add
before_remove
If you register an association callback on your model class, it is invoked whenever you add or remove a document from any of the following associations:
embeds_many
has_many
has_and_belongs_to_many
Specify association callbacks as options on the respective association. You must pass the added or removed document as the parameter to the specified callback.
The following code demonstrates how to register an association callback
on a User
model class that embeds multiple SavedArticle
instances to limit the number of embedded documents for a single
instance:
class User include Mongoid::Document field :username, type: String # Registers the callback in the association statement embeds_many :saved_articles, before_add: :send_message protected # Passes the association document as a parameter to the callback def send_message(saved_article) if saved_articles.count >= 10 p "you can't save more than 10 articles at a time" throw(:abort) end end end class SavedArticle include Mongoid::Document embedded_in :user field :url, type: String end
Additional Information
To learn how to prevent Mongoid from running callbacks, see the following references in the Active Record documentation:
To learn about how Mongoid manages callbacks in transactions, see the Transactions and Sessions guide.
To learn how to access and change your MongoDB data, see the Interact with Data guides.