ruby on rails - seguridad - ¿Devolución de llamada para cambiar los atributos de ActiveRecord?
seguridad en ruby on rails (6)
La forma más fácil que encontré:
after_save :my_method, :if => Proc.new{ self.my_attribute_changed? }
def my_method
... do stuff...
end
Soy consciente de ActiveRecord :: Dirty y los métodos relacionados, pero no veo un medio por el cual pueda suscribirme a un evento de cambio de atributo. Algo como:
class Person < ActiveRecord::Base
def attribute_changed(attribute_name, old_value, new_value)
end
#or
attribute_changed do |attribute_name, old_value, new_value|
end
end
¿Hay un estándar de Rails o plugin para esto? Siento que debe estar allí en algún lugar y solo me lo estoy perdiendo.
La respuesta de cwninja debería hacer el truco, pero hay un poco más.
En primer lugar, el manejo de los atributos básicos se realiza con el método write_attribute, por lo que debería aprovechar esto.
Los rieles también tienen una estructura de devolución de llamada incorporada que podría ser agradable de utilizar, aunque no permite pasar argumentos, lo que es un poco molesto.
Usando devoluciones de llamada personalizadas, podrías hacerlo así:
class Person < ActiveRecord::Base
def write_attribute(attr_name, value)
attribute_changed(attr_name, read_attribute(attr_name), value)
super
end
private
def attribute_changed(attr, old_val, new_val)
logger.info "Attribute Changed: #{attr} from #{old_val} to #{new_val}"
end
end
Si quisiera tratar de usar las devoluciones de llamada de Rails (especialmente útil si puede tener múltiples devoluciones de llamada y / o subclases) podría hacer algo como esto:
class Person < ActiveRecord::Base
define_callbacks :attribute_changed
attribute_changed :notify_of_attribute_change
def write_attribute(attr_name, value)
returning(super) do
@last_changed_attr = attr_name
run_callbacks(:attribute_changed)
end
end
private
def notify_of_attribute_change
attr = @last_changed_attr
old_val, new_val = send("#{attr}_change")
logger.info "Attribute Changed: #{attr} from #{old_val} to #{new_val}"
end
end
Para rieles 3:
class MyModel < ActiveRecord::Base
after_update :my_listener, :if => :my_attribute_changed?
def my_listener
puts "Attribute ''my_attribute'' has changed"
end
end
Comentado en: https://.com/a/1709956/316700
No encuentro documentación oficial sobre esto.
Para rieles 4
def attribute=(value)
super(value)
your_callback(self.attribute)
end
Si desea sobrescribir el valor del atributo, debe usar write_attribute(:attribute, your_callback(self.attribute))
y no attribute=
o lo superará hasta que obtenga una excepción de pila demasiado profunda.
Siempre se puede acceder al método privado changed_attributes
y verificar las claves allí usando a before_save
y hacer con él lo que quieras.
tratar:
def attribute_changed(attribute_name, old_value, new_value)
end
def attribute=(attribute_name, value)
returning(super) do
attribute_changed(attribute_name, attribute_was(attribute_name), attribute(attribute_name))
end
end
Acabo de inventar esto ahora, pero debería funcionar.