ruby on rails - que - Rails 3 comprueba si el atributo ha cambiado
ruby on rails que es (4)
Eche un vistazo a ActiveModel::Dirty (disponible en todos los modelos por defecto). La documentación es realmente buena, pero te permite hacer cosas como:
@user.street1_changed? # => true/false
Necesita verificar 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 pedazo de código será REALMENTE largo. ¿Hay una manera más limpia?
Las respuestas anteriores son mejores, pero aun así, para conocimiento, tenemos otra aproximación, permite cambiar el valor de la columna ''catagory'' para un objeto (@design),
@design.changes.has_key?(''catagory'')
Los .changes devolverán un hash con clave como el nombre y los valores de la columna como una matriz con dos valores [old_value, new_value] para cada columna. Por ejemplo, la categoría de arriba se cambia de ''ABC'' a ''XYZ'' de @design,
@design.changes # => {}
@design.catagory = ''XYZ''
@design.changes # => { ''catagory'' => [''ABC'', ''XYZ''] }
Para referencias, cambio en ROR
ActiveModel::Dirty
no funcionó para mí porque @model.update_attributes()
ocultó los cambios. Entonces, así es como detecté los cambios en un método de 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
Sin embargo, si intentas detectar muchos cambios de atributos, podría ser complicado. Probablemente no debería hacer esto en un controlador, pero meh.
Así es como resolví el problema de verificar cambios en múltiples atributos.
attrs = ["street1", "street2", "city", "state", "zipcode"]
if (@user.changed & attrs).any?
then do something....
end
El método changed
devuelve una matriz de los atributos modificados para ese objeto.
Both @user.changed
y attrs
son matrices, así que puedo obtener la intersección (ver ary & other ary
método ary & other ary
). El resultado de la intersección es una matriz. Al llamar a any?
en la matriz, me hago verdadero si hay al menos una intersección.
También muy útil, el método changed_attributes
devuelve un hash de los atributos con sus valores originales y los changes
devuelven un hash de los atributos con sus valores originales y nuevos (en una matriz).
Puede verificar APIDock para qué versiones admiten estos métodos.