tengo una serie como estaguardar una matriz activa registros
a = []
a << B.new(:name => "c")
a << B.new(:name => "s")
a << B.new(:name => "e")
a << B.new(:name => "t")
Cómo me puedo guardarlo a la vez?
tengo una serie como estaguardar una matriz activa registros
a = []
a << B.new(:name => "c")
a << B.new(:name => "s")
a << B.new(:name => "e")
a << B.new(:name => "t")
Cómo me puedo guardarlo a la vez?
a.each(&:save)
Para ello, será B#save
en cada elemento de la matriz.
B.transaction do
a.each(&:save!)
end
Esto creará una transacción que recorre cada elemento de la matriz y llama a element.save en ella.
Puede leer sobre ActiveRecord Transactions y the each method en las API de Rails y Ruby.
Envolver save
en la transacción no será suficiente: si una validación no se pasa, no será una excepción levantada y sin reversión disparado.
puedo sugerir esto:
B.transaction do
a.each do |o|
raise ActiveRecord::Rollback unless o.save
end
end
Sólo haciendo B.transaction do a.each(&:save!) end
no es una opción ya sea, porque el bloque de transacción no rescatará ninguna excepción que no sea ActiveRecord::Rollback
, y la aplicación se estrellaría en la validación fallida.
No sé cómo verificar después si los registros se han guardado.
actualización. Como alguien ha downrated mi respuesta, supongo que la persona que estaba buscando una solución de cortar y pegar :), asi que aquí hay alguna manera (feo :)) para procesar Falla/valor éxito:
save_failed = nil
B.transaction do
a.each do |o|
unless o.save
save_failed = true
raise ActiveRecord::Rollback
end
end
end
if save_failed
# ...
else
# ...
end
'¡guardar!'es perfecto, el bloque' transaction do' revertirá automáticamente todos los demás cambios. – reto
Debería detectar excepciones manualmente fuera de la transacción si falla una validación. – Alexey
Todo lo que digo es: tienes dos opciones a) manejar la validación inmediatamente después del 'save' usando el valor de retorno b) dejar que el proceso/trabajo se cuelgue usando' save! ', Hay (en casi todos los casos) no hay término medio. Un 'save' solitario (sin manejar su valor de retorno) es una gran señal de advertencia. La transacción simplemente asegura que todo lo demás se restaure también. – reto
Así Creo que necesitamos un término medio para las excepciones de Alexey y abortar la transacción y la solución única de Jordan. ¿Puedo proponer:
B.transaction do
success = a.map(&:save)
unless success.all?
errored = a.select{|b| !b.errors.blank?}
# do something with the errored values
raise ActiveRecord::Rollback
end
end
Esto le dará un poco de ambos mundos: una transacción con rollback, el conocimiento de que registra e incluso no le da acceso a los errores de validación en el mismo.
Sé que esto es una vieja pregunta, pero estoy sorprendido nadie pensó en esto:
B.transaction do
broken = a.reject { |o| o.save }
raise ActiveRecord::Rollback if broken.present?
end
if broken.present?
# error message
end
¡Debería usar guardar! en lugar del aumento. La transacción se encargará del resto. –
@ D.Wonnink sí, pero provocará un cortocircuito en las copias de seguridad adicionales, por lo que solo sabrá sobre la primera que falló, no sobre todas ellas. Esto puede hacer una gran diferencia cuando tienes, por ejemplo, 30 objetos guardados en fila, la mitad de ellos fallaron y tienes que mostrar la validación al usuario de una manera que no lo hará volver a enviar el formulario 15 veces para corregir 15 errores uno después de otro solo para aprender, otra cosa está rota;) – d4rky
En caso de que usted está buscando la solución más eficiente que ahorre cada fila en el bucle busque mi respuesta aquí Ruby on Rails - Import Data from a CSV file
Estoy sugiriendo usar gema activerecord-import
allí.
Y envuelva eso en una B.transaction para que todo se guarde en una operación atómica. – Farrel
Nunca llame 'save', revise el valor de retorno (true oder false) o use' .save! 'Para permitir que los rails hagan una excepción cuando algo no está bien. – reto