Overview
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.
Funciones de retorno soportadas
Mongoid admite las siguientes devoluciones de llamadas en clases de modelo que implementan el Document module:
after_initializeafter_buildbefore_validationafter_validationbefore_createaround_createafter_createafter_findbefore_updatearound_updateafter_updatebefore_upsertaround_upsertafter_upsertbefore_savearound_saveafter_savebefore_destroyaround_destroyafter_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.
Nota
Comportamiento de invocación de devolución de llamada
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.
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.
Devoluciones de llamada de documento
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étodoprocess_phoneantes de que se guarde una instanciaContacten MongoDB. El métodoprocess_phonese define por separado en la clase.Incluye el método de clase
after_destroyy utiliza un bloque para imprimir un mensaje cuando se elimina una instanciaContact.
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 devolución de llamada:
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"}
Funciones de retorno de asociación
Mongoid proporciona las siguientes devoluciones de llamadas de asociación:
after_addafter_removebefore_addbefore_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_manyhas_manyhas_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
Variables Limited-Thread
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.
Información Adicional
Para saber cómo evitar que Mongoid ejecute devoluciones de llamadas, consulte 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.