Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

Personalizar devoluciones de llamada para modelos

En esta guía, puedes aprender cómo implementar retrollamadas en tus modelos Mongoid para personalizar el ciclo de vida de tus instancias de modelo.

Los callbacks son métodos que Mongoid activa en momentos específicos del ciclo de vida de un objeto. Permiten iniciar acciones específicas antes o después de cambios en el estado de un objeto.

Mongoid implementa muchas de las devoluciones de llamada provenientes de Active Record. Para obtener más información, consulte función de retorno en la documentación de Active Record.

Mongoid admite las siguientes devoluciones de llamada en las clases de modelos que implementan la 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

Para obtener más información sobre cualquiera de los tipos de callback anteriores, consulta la referencia ActiveRecord::Callbacks en la documentación de la API de Rails.

Puedes implementar funciones de retorno en modelos de documentos tanto de nivel superior como incrustados.

Toma precauciones y asegúrate de la capacidad de prueba al implementar funciones de retorno para lógica de dominio, ya que estos diseños pueden llevar a errores inesperados cuando las funciones de retorno en la cadena detienen la ejecución. Recomendamos usar funciones de retorno para preocupaciones transversales fuera de la funcionalidad principal de tu programa, como la cola de tareas en segundo plano.

Para mayor eficiencia, Mongoid invoca la función de retorno únicamente en el documento sobre el cual se realizó la acción de persistencia. Este comportamiento permite que Mongoid admita grandes jerarquías y gestione actualizaciones atómicas optimizadas de manera eficiente al no invocar callbacks en toda la jerarquía del documento.

A partir de Mongoid v9.0.7, si tienes un parent document que cambia de state, las funciones de retorno del child document solo se invocan si el child document ha cambiado. Anteriormente, las devoluciones de llamada del child también se invocaban cuando el document parent cambiaba.

Para invocar funciones de retorno secundarias cuando el document principal cambia, hay que iterar explícitamente sobre los elementos secundarios dentro de una función de retorno principal. Por ejemplo, puedes implementar una función de retorno principal que recorra los hijos e invoque las funciones de retorno de los hijos, como se muestra en el siguiente ejemplo:

class Parent
include Mongoid::Document
has_many :children
after_save { children.each(&:parent_changed_callback) }
end
class Child
include Mongoid::Document
belongs_to :parent
def parent_changed_callback
# ...
end
end

Se deben implementar y registrar funciones de retorno en las clases de modelos. Puede registrar una función de retorno utilizando métodos ordinarios, bloques y objetos Proc, o definir objetos de función de retorno personalizados que utilicen clases o módulos.

Este ejemplo demuestra cómo registrar funciones de retorno en la clase de modelo Contact de las siguientes maneras:

  • Incluye el método de clase before_save, que activa el método process_phone antes de que se guarde una instancia Contact en MongoDB. El método process_phone se define por separado en la clase.

  • Incluye el método de clase after_destroy y utiliza un bloque para imprimir un mensaje cuando se elimina una instancia de Contact.

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

El siguiente código realiza operaciones de datos que demuestran las acciones de la función de retorno:

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"

Como la funcionalidad de callbacks proviene de Active Support, también se puede usar la sintaxis del método de clase set_callback para registrar callbacks. El siguiente código demuestra cómo utilizar esta sintaxis para crear una función de retorno que almacene los valores originales del campo name en el arreglo aliases:

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"}

Mongoid proporciona los siguientes callbacks de asociación:

  • after_add

  • after_remove

  • before_add

  • before_remove

Si registras una función de retorno de asociación en tu clase de modelo, se invoca cada vez que agregas o remueves un documento de cualquiera de las siguientes asociaciones:

  • embeds_many

  • has_many

  • has_and_belongs_to_many

Especifica los callbacks de asociación como opciones en la asociación correspondiente. Debes pasar el documento añadido o eliminado como parámetro a la función de retorno especificada.

El siguiente código demuestra cómo registrar una función de retorno de asociación en una clase de modelo User que incrusta varias instancias de SavedArticle para limitar el número de documentos incrustados para una sola instancia:

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

Si tienes documentos secundarios incrustados en una asociación que tiene cascade_callbacks: true configurado, entonces las devoluciones de llamada secundarias incrustadas se ejecutan dentro de un Fiber Ruby. Esto significa que, si utilizas los métodos Thread#[] y Thread#[]= para obtener y establecer variables locales de fibra, esas funciones de retorno no leen ni establecen los valores que esperas.

Recomendamos utilizar los métodos Thread#thread_variable_get y Thread#thread_variable_set para obtener y establecer variables verdaderamente locales de subproceso. Para mayor comodidad, Mongoid v9.0.3 introduce los métodos Mongoid::Threaded.get y Mongoid::Threaded.set para implementar esta funcionalidad.

Para aprender cómo prevenir que Mongoid ejecute callbacks, consulta las siguientes referencias en la documentación de Active Record:

Para aprender sobre cómo Mongoid gestiona las funciones de retorno en las transacciones, consulta la guía Transacciones y Sesiones.

Para aprender a acceder y modificar tus datos en MongoDB, consulta las guías de Interacción con Datos.

Volver

particionado

En esta página