ruby-on-rails - que - ruby on rails tutorial
Rails update_attributes sin guardar? (4)
¿Hay una alternativa a update_attributes que no guarde el registro?
Entonces podría hacer algo como:
@car = Car.new(:make => ''GMC'')
#other processing
@car.update_attributes(:model => ''Sierra'', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save
Por cierto, sé que puedo @car.model = ''Sierra''
, pero quiero actualizarlos todos en una sola línea.
Creo que lo que estás buscando es assign_attributes
.
Básicamente es lo mismo que update_attributes pero no guarda el registro:
class User < ActiveRecord::Base
attr_accessible :name
attr_accessible :name, :is_admin, :as => :admin
end
user = User.new
user.assign_attributes({ :name => ''Josh'', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => ''Bob''})
user.name # => "Bob"
user.is_admin? # => false
user.new_record? # => true
Para la asignación masiva de valores a un modelo ActiveRecord sin guardar, use los attributes=
assign_attributes
o attributes=
. Estos métodos están disponibles en Rails 3 y más nuevos. Sin embargo, hay pequeñas diferencias y errores relacionados con la versión que hay que tener en cuenta.
Ambos métodos siguen este uso:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }
@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }
Tenga en cuenta que ninguno de los métodos realizará validaciones ni ejecutará devoluciones de llamada; Las devoluciones de llamada y la validación sucederán cuando se llame a save
.
Rieles 3
attributes=
difiere ligeramente de assign_attributes
en Rails 3. attributes=
comprobará que el argumento que se le pasa es un hash, y devuelve inmediatamente si no lo es; assign_attributes
no tiene tal verificación de Hash. Consulte la documentación de la API de Asignación de Atributos de ActiveRecord para attributes=
.
El siguiente código inválido fallará silenciosamente simplemente regresando sin establecer los atributos:
@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]
attributes=
se comportará silenciosamente como si las asignaciones se hubieran realizado con éxito, cuando en realidad no lo eran.
Este código no válido generará una excepción cuando assign_attributes
intente clasificar las claves hash de la matriz que lo contiene:
@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])
assign_attributes
generará una excepción NoMethodError
para stringify_keys
, lo que indica que el primer argumento no es un Hash. La excepción en sí no es muy informativa sobre la causa real, pero el hecho de que ocurra una excepción es muy importante.
La única diferencia entre estos casos es el método utilizado para la asignación masiva: los attributes=
éxito silencioso, y los assign_attributes
generan una excepción para informar que se ha producido un error.
Estos ejemplos pueden parecer artificiales, y hasta cierto punto, pero este tipo de error puede ocurrir fácilmente al convertir datos de una API, o incluso simplemente usar una serie de transformación de datos y olvidarse de Hash[]
los resultados del .map
final. . Mantenga un código de 50 líneas arriba y 3 funciones eliminadas de su asignación de atributos, y tiene una receta para el fracaso.
La lección con Rails 3 es la siguiente: siempre use assign_attributes
lugar de attributes=
.
Rieles 4
En Rails 4, attributes=
es simplemente un alias para assign_attributes
. Consulte la documentación de la API de Asignación de Atributos de ActiveRecord para attributes=
.
Con Rails 4, cualquiera de los dos métodos puede ser usado indistintamente. Si no se pasa un Hash, el primer argumento resultará en una excepción muy útil: ArgumentError: When assigning attributes, you must pass a hash as an argument.
Validaciones
Si está realizando tareas previas al vuelo en preparación para save
, también podría estar interesado en validar antes de guardar. Puedes usar el valid?
e invalid?
Métodos para esto. Ambos devuelven valores booleanos. valid?
devuelve verdadero si el modelo no guardado pasa todas las validaciones o falso si no lo hace. invalid?
¿Es simplemente el inverso de valid?
valid?
se puede utilizar de esta manera:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?
Esto le dará la posibilidad de manejar cualquier problema de validación antes de save
llamadas.
Puede utilizar el método de ''atributos'':
@car.attributes = {:model => ''Sierra'', :years => ''1990'', :looks => ''Sexy''}
Fuente: http://api.rubyonrails.org/classes/ActiveRecord/Base.html
attributes = (new_attributes, guard_protected_attributes = true) Le permite establecer todos los atributos a la vez al pasar un hash con claves que coinciden con los nombres de los atributos (que nuevamente coinciden con los nombres de las columnas).
Si guard_protected_attributes es verdadero (el valor predeterminado), los atributos confidenciales pueden protegerse de esta forma de asignación masiva utilizando la macro attr_protected O también puede especificar a qué atributos se puede acceder con la macro attr_accessible. Entonces todos los atributos no incluidos en eso no podrán ser asignados en masa.
class User < ActiveRecord::Base
attr_protected :is_admin
end
user = User.new
user.attributes = { :username => ''Phusion'', :is_admin => true }
user.username # => "Phusion"
user.is_admin? # => false
user.send(:attributes=, { :username => ''Phusion'', :is_admin => true }, false)
user.is_admin? # => true
Puedes usar assign_attributes
o attributes=
(son los mismos)
Métodos de actualización de la hoja de trucos (para Rails 4):
-
update_attributes
=assign_attributes
+save
-
attributes=
= alias deassign_attributes
-
update
= alias deupdate_attributes
Fuente:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb
Otra hoja de trucos:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet