Ayuda con callbacks

Holas, a ver si alguien me puede echar una mano con los callbacks…

Tengo una aplicación con un modelo Producto donde quiero que cada vez
que se modifique, se apunte en un histórico los campos que han
cambiado. En plan: “Precio cambia de 100 € a 125 €, color cambia a
rojo”, en un modelo Historico asociado a Producto.

Para ello pensaba hacerlo con callbacks de manera que antes del update
de producto me hiciera una copia temporal del producto, y después del
update comparo qué campos han cambiado y lo anoto en el histórico. Una
cosa
así:
class Producto
has_many :historicos

before_validation_on_update :apunta_datos
before_update :apunta_historico

def apunta_datos
@producto_bak = self.clone
end

def apunta_historico
cambios = “”
if self.precio != @producto_bak.precio
cambios += “Precio cambia de #{@producto_bak.precio} a
#{self.precio}”
end

if (cambios != "")
  self.historicos.create(:cambios => cambios)
end

end
end

Pero esto no funciona porque todos los before_* callbacks tienen lugar
una vez que se ha modificado el objeto, y no antes. O sea que lo que
apunto con self.clone ya es el objeto modificado, con lo que siempre
compara 125 € con 125 €…

¿Cuál es la mejor forma de hacer esto? ¿Mejor desde el controlador?

hola,

before_validation_on_update :apunta_datos

puedes implementar eso mismo en el callback after_find. Te hará los find
de ese modelo algo más lentos, pero probablemente es asumible.

saludos,

javier ramírez

2008/3/25, javier ramirez [email protected]:

puedes implementar eso mismo en el callback after_find. Te hará los find
de ese modelo algo más lentos, pero probablemente es asumible.

Gracias Javier, tiene buena pinta. Aunque lo he probado y creo que
tengo un problema de visibilidad de variables, en mi apunta_historico
(after_update) no sabe lo que es @producto_bak que se crea en
apunta_datos (after_find).

El 25/03/08, javier ramirez [email protected]
escribió:>

te lo comento por si acaso, no sea que no se esté ejecutando tu
after_find. Por lo demás, la variable debería verse sin problemas.

Ei! Era justo eso. Ahora sí que me funciona, gracias de nuevo!

Es una pena no poder limitarlo al find de justo antes del update, pero
me vale. Gracias!

buenas,

Gracias Javier, tiene buena pinta. Aunque lo he probado y creo que
tengo un problema de visibilidad de variables, en mi apunta_historico
(after_update) no sabe lo que es @producto_bak que se crea en
apunta_datos (after_find).

ten en cuenta, por si acaso, que el after_find es como el
after_initialize, algo especiales. No puedes hacer esto

after_find :metodo

tienes que hacer explícitamente

def after_find
#tu código
end

te lo comento por si acaso, no sea que no se esté ejecutando tu
after_find. Por lo demás, la variable debería verse sin problemas.

Yo en un proyecto antiguo que hice tengo un after_find definido así

def after_find
@row_cache = User.new(self.attributes.dup)
self.email_confirmation = self.email
self.paypal_account_confirmation = self.paypal_account
end

y luego utilizo el @row_cache sin problemas en un before_update

suerte,

javier ramírez