-
Notifications
You must be signed in to change notification settings - Fork 29
DOCSP-45361: callbacks #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,173 @@ | ||||||
.. _mongoid-modeling-callbacks: | ||||||
|
||||||
========= | ||||||
Callbacks | ||||||
========= | ||||||
|
||||||
.. facet:: | ||||||
:name: genre | ||||||
:values: reference | ||||||
|
||||||
.. meta:: | ||||||
:keywords: ruby framework, odm, code example, life cycle | ||||||
|
||||||
.. contents:: On this page | ||||||
:local: | ||||||
:backlinks: none | ||||||
:depth: 2 | ||||||
:class: singlecol | ||||||
|
||||||
Overview | ||||||
-------- | ||||||
|
||||||
In this guide, you can learn how to implement **callbacks** in your | ||||||
{+odm+} models to customize the life cycle of your model instances. | ||||||
|
||||||
Callbacks are methods that {+odm+} 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. | ||||||
|
||||||
{+odm+} implements many of the callbacks from Active Record. To learn | ||||||
more, see `Callbacks | ||||||
<{+active-record-docs+}/active_record_callbacks.html>`__ in the | ||||||
Active Record documentation. | ||||||
|
||||||
Supported Callbacks | ||||||
------------------- | ||||||
|
||||||
Mongoid supports the following callbacks on model classes that implement | ||||||
the :ref:`Document <mongoid-modeling-documents>` 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`` | ||||||
Check failure on line 58 in source/data-modeling/callbacks.txt
|
||||||
- ``around_destroy`` | ||||||
Check failure on line 59 in source/data-modeling/callbacks.txt
|
||||||
- ``after_destroy`` | ||||||
Check failure on line 60 in source/data-modeling/callbacks.txt
|
||||||
|
||||||
To learn more about any of the preceding callback types, see the | ||||||
`ActiveRecord::Callbacks | ||||||
<https://api.rubyonrails.org/{+rails-8-version-docs+}/classes/ActiveRecord/Callbacks.html>`__ | ||||||
reference in the Rails API documentation. | ||||||
|
||||||
You can implement a callback both top-level and embedded documents. | ||||||
|
||||||
.. note:: Callback Invocation Behavior | ||||||
|
||||||
For efficiency, {+odm+} invokes the callback only on the document | ||||||
that you performed the persistence action on. This behavior enables | ||||||
{+odm+} 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, 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 the | ||||||
|
- Includes the ``before_save`` class method which triggers the | |
- Includes the ``before_save`` class method, which triggers the |
Check failure on line 97 in source/data-modeling/callbacks.txt
GitHub Actions / TDBX Vale rules
[vale] reported by reviewdog 🐶
[MongoDB.NegativeWords] Use 'remove, delete' instead of the negative word 'destroy'.
Raw Output:
{"message": "[MongoDB.NegativeWords] Use 'remove, delete' instead of the negative word 'destroy'.", "location": {"path": "source/data-modeling/callbacks.txt", "range": {"start": {"line": 97, "column": 24}}}, "severity": "ERROR"}
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
S: might be helpful to describe this code more in-depth, similar to the description for the "Document Callbacks" example. Right now it's not super clear how it works
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I: Looks like there isn't a "suppressing callbacks" section on this page, did you mean "suppressing saving"?
- `Suppressing Callbacks <{+active-record-docs+}/active_record_callbacks.html#suppressing-callbacks>`__ | |
- `Suppressing Saving <{+active-record-docs+}/active_record_callbacks.html#suppressing-saving>`__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops!
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# start-doc-callback | ||
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 | ||
# end-doc-callback | ||
|
||
# start-doc-ops | ||
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" | ||
# end-doc-ops | ||
|
||
# start-doc-set-syntax | ||
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"} | ||
# end-doc-set-syntax | ||
|
||
# start-association-callback | ||
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 | ||
# end-association-callback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
S: