Rails 3 comprobar si el atributo ha cambiado
Es necesario comprobar si un bloque de atributos ha cambiado antes de la actualización en Rails 3.
Street1, street2, city, state, zipcode
Sé que podría usar algo como
if @user.street1 != params[:user][:street1]
then do something....
end
Pero ese fragmento de código será MUY largo. ¿Hay una manera más limpia?
5 answers
Echa un vistazo a ActiveModel::Dirty (disponible en todos los modelos por defecto). La documentación es muy buena, pero te permite hacer cosas como:
@user.street1_changed? # => true/false
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 13:57:59
Así es como resolví el problema de comprobar si hay cambios en múltiples atributos.
attrs = ["street1", "street2", "city", "state", "zipcode"]
if (@user.changed & attrs).any?
then do something....
end
El changed
method devuelve una matriz de los atributos modificados para ese objeto.
Ambos @user.changed
y attrs
son matrices para que pueda obtener la intersección (ver ary & other ary
método). El resultado de la intersección es una matriz. Al llamar a any?
en la matriz, obtengo true si hay al menos una intersección.
También muy útil, el changed_attributes
método devuelve un hash de los atributos con sus valores originales y changes
devuelve un hash de los atributos con sus valores originales y nuevos (en una matriz).
Puede comprobar APIDock para qué versiones soportaban estos métodos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-26 21:22:16
ActiveModel::Dirty
no funcionó para mí porque el @model.update_attributes()
ocultó los cambios. Así es como detecté los cambios en un método update
en un controlador:
def update
@model = Model.find(params[:id])
detect_changes
if @model.update_attributes(params[:model])
do_stuff if attr_changed?
end
end
private
def detect_changes
@changed = []
@changed << :attr if @model.attr != params[:model][:attr]
end
def attr_changed?
@changed.include :attr
end
Si usted está tratando de detectar una gran cantidad de cambios de atributos que podría conseguir desordenado sin embargo. Probablemente no debería hacer esto en un controlador, pero meh.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-04 21:56:52
Las respuestas anteriores son mejores, pero sin embargo para el conocimiento tenemos otro enfoque también, Permite cambiar el valor de la columna' catagory ' para un objeto (@design),
@design.changes.has_key?('catagory')
El.los cambios devolverán un hash con clave como nombre de columna y valores como una matriz con dos valores [old_value, new_value] para cada columna. Por ejemplo, catagory para arriba se cambia de ' ABC 'a' XYZ ' de @design,
@design.changes # => {}
@design.catagory = 'XYZ'
@design.changes # => { 'catagory' => ['ABC', 'XYZ'] }
For references change in ROR
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-17 11:47:16
Para rails 5.1 + callbacks
Para mejorar este post y completar otras respuestas
La primera respuesta quedará obsoleta para las devoluciones de llamada en las siguientes versiones de rails (después de la 5.1).
Así que la nueva forma de comprobar si un atributo ha cambiado es con saved_change_to_attribute?
Puedes hacer:
@user.saved_change_to_street1? # => true/false
Puedes ver más ejemplos aquí en este post blog
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-21 20:42:03