¿Determinar qué atributos se cambiaron en la devolución de llamada after_save de Rails?
Estoy configurando una devolución de llamada after_save en mi observador de modelo para enviar una notificación solo si el atributo publicado del modelo se cambió de falso a verdadero. ¿Desde que métodos como estos cambiaron? solo son útiles antes de guardar el modelo, la forma en que estoy intentando hacerlo actualmente (y sin éxito) es la siguiente:
def before_save(blog)
@og_published = blog.published?
end
def after_save(blog)
if @og_published == false and blog.published? == true
Notification.send(...)
end
end
¿Alguien tiene alguna sugerencia sobre la mejor manera de manejar esto, preferiblemente usando devoluciones de llamada de observador de modelo (para no contaminar el código de mi controlador)?
Rieles 5.1+
Usar saved_change_to_published?
:
class SomeModel < ActiveRecord::Base
after_update :send_notification_after_change
def send_notification_after_change
Notification.send(…) if (saved_change_to_published? && self.published == true)
end
end
O si lo prefieres, saved_change_to_attribute?(:published)
.
Rieles 3–5.1
Advertencia
Este enfoque funciona a través de Rails 5.1 (pero está obsoleto en 5.1 y tiene cambios importantes en 5.2). Puede leer sobre el cambio en esta solicitud de extracción .
En su after_update
filtro sobre el modelo puede utilizar _changed?
el descriptor de acceso. Así por ejemplo:
class SomeModel < ActiveRecord::Base
after_update :send_notification_after_change
def send_notification_after_change
Notification.send(...) if (self.published_changed? && self.published == true)
end
end
Simplemente funciona.
Para aquellos que quieran conocer los cambios que acaban de realizar en una after_save
devolución de llamada:
Rieles 5.1 y superiores
model.saved_changes
Rieles < 5,1
model.previous_changes
Consulte también: http://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-previous_changes
Para cualquiera que vea esto más adelante, ya que actualmente (agosto de 2017) encabeza Google: vale la pena mencionar que este comportamiento se modificará en Rails 5.2 y tiene advertencias de obsolescencia a partir de Rails 5.1, ya que ActiveModel::Dirty cambió un poco. .
¿Qué cambio?
Si está utilizando attribute_changed?
el método en las after_*
devoluciones de llamada, verá una advertencia como:
ADVERTENCIA DE DEPRECACIÓN: El comportamiento de
attribute_changed?
las devoluciones de llamada internas y posteriores cambiará en la próxima versión de Rails. El nuevo valor de retorno reflejará el comportamiento de llamar al método despuéssave
del retorno (por ejemplo, lo opuesto a lo que devuelve ahora). Para mantener el comportamiento actual, utilicesaved_change_to_attribute?
en su lugar. (llamado desde some_callback en /PATH_TO/app/models/user.rb:15)
Como se menciona, puedes solucionar este problema fácilmente reemplazando la función con saved_change_to_attribute?
. Así, por ejemplo, name_changed?
se convierte en saved_change_to_name?
.
Del mismo modo, si estás usando attribute_change
para obtener los valores de antes y después, esto también cambia y arroja lo siguiente:
ADVERTENCIA DE DEPRECACIÓN: El comportamiento de
attribute_change
las devoluciones de llamada internas y posteriores cambiará en la próxima versión de Rails. El nuevo valor de retorno reflejará el comportamiento de llamar al método despuéssave
del retorno (por ejemplo, lo opuesto a lo que devuelve ahora). Para mantener el comportamiento actual, utilicesaved_change_to_attribute
en su lugar. (llamado desde some_callback en /PATH_TO/app/models/user.rb:20)
Nuevamente, como menciona, el método cambia de nombre al saved_change_to_attribute
que devuelve ["old", "new"]
. o use saved_changes
, que devuelve todos los cambios y se puede acceder a ellos como saved_changes['attribute']
.
En caso de que puedas hacer esto before_save
en lugar de after_save
, podrás usar esto:
self.changed
devuelve una matriz de todas las columnas modificadas en este registro.
también puedes usar:
self.changes
que devuelve un hash de columnas que cambiaron y resultados antes y después como matrices