2009-10-19 10 views
71

Me gustaría crear una función de devolución de llamada en los rieles que se ejecuta después de guardar un modelo.Cómo detectar cambios de atributo del modelo?

que tienen este modelo, Reclamación que tiene un atributo 'estado', que cambia en función del estado de la reclamación, los valores posibles están pendientes, aprobado, aprobado, rechazado

La base de datos tiene 'estado' con el valor por defecto valor de 'pendiente'.

Me gustaría realizar ciertas tareas después de que el modelo se crea la primera vez o se actualiza de un estado a otro, dependiendo de qué estado cambie.

Mi idea es tener una función en el modelo:

after_save :check_state 

    def check_state 
     # if status changed from nil to pending (created) 
     do this 

     # if status changed from pending to approved 
     performthistask 
    end 

Mi pregunta es ¿cómo puedo comprobar el valor anterior antes del cambio en el modelo?

Respuesta

148

usted debe buscar en ActiveModel::Dirty módulo: Usted debe ser capaz de realizar las acciones siguientes en el modelo de reclamación:

claim.status_changed? # returns true if 'status' attribute has changed 
claim.status_was  # returns the previous value of 'status' attribute 
claim.status_change # => ['old value', 'new value'] returns the old and 
         # new value for 'status' attribute 

claim.name = 'Bob' 
claim.changed # => ["name"] 
claim.changes # => {"name" => ["Bill", "Bob"]} 

Oh! las alegrías de Rails!

+4

Esto no funcionará después de guardar el modelo, que es lo que pidió. –

+3

@TomRossi, las llamadas 'dirty' funcionan en' after_save' (ambas en Rails 2.3 y 3.x). Lo he usado varias veces –

+8

@TomRossi, las banderas sucias se restablecen después de la confirmación, por lo que no estarán disponibles en las devoluciones de llamada 'after_commit' introducidas en Rails 3.x. Ciertamente funcionarán en 'after_save'. –

3

te recomiendo echar un vistazo a uno de los plugins de máquina de estados disponibles:

Cualquiera de los dos permitirá estados de configuración y las transiciones entre estados. Manera muy útil y fácil de manejar sus requerimientos.

+0

Estoy probando rubyist-aasm. Digamos que tengo Reclamación clase : enter_pending def enter_pending notificador.deliver_pending_notification (self) end end Y mi campo de estado en mi base de datos tiene el valor predeterminado de "pendiente". Si tuviera que crear un Claim.create sin rellenar el campo de estado (para que se ejecute 'pending'), ¿AASM ejecutará el método 'enter_pending'? –

33

puede utilizar esta

self.changed 

que devolver una matriz de todas las columnas que han cambiado en este registro

también puede utilizar

self.changes 

que devuelve un hash de columnas que han cambiado y antes y después de los resultados como matrices

+4

Solo una pequeña nota para decir que no es necesario usar' self' en estos - solo puede decir 'changed' y 'cambios'. – user664833

0

He visto aumentar la pregunta en en muchos lugares, así que escribí un rubí minúsculo para él, para hacer que el código sea un poco más agradable (y evitar un millón de declaraciones if/else en todas partes): https://github.com/ronna-s/on_change. Espero que eso ayude.

0

Será mucho mejor si utiliza una solución bien probada, como la gema state_machine.

Cuestiones relacionadas