En rieles, ¿cómo puedo averiguar qué causó que un .save () fallara, además de los errores de validación?

91

Tengo un modelo de ActiveRecord que regresa truede valid?(y .errors está vacío), pero regresa falsede save(). Si la instancia del modelo es válida, ¿cómo puedo averiguar qué está causando que el guardado falle?

kdt
fuente
7
Tuve este problema hace un par de semanas. Algunas refactorizaciones habían dejado una función before_save que devolvía false todo el tiempo, lo que provoca que el guardado falle.
Jeff Paquette
1
@Jeff - gracias, resulta que hubo un método: before_save que devolvió falso. ¿Como lo descubriste? ¿Fue solo una inspección de código?
kdt
Fue una inspección de código y hacer diferencias contra el control de versiones.
Jeff Paquette

Respuestas:

49

Revise todas sus devoluciones de llamada.

Tuve un problema como este en el que tenía un método "after_validate" que fallaba después de haber realizado un montón de cambios en el modelo. El modelo era válido pero "after_validate" devolvía falso, así que si usémodel.valid decía verdadero, pero luego si lo guardaba me daba errores de validación (pasados ​​de la devolución de llamada after_validate). Fue raro.

Mire el seguimiento de la aplicación y debería poder ver qué línea de código está generando la excepción.

Andrés
fuente
2
Según el comentario de Jeff, el problema resultó ser una devolución de llamada before_save que devolvía falso.
kdt
3
@kdt - ese era exactamente mi problema. No lo había pensado porque before_save solo estaba destinado a establecer una propiedad, pero debido a que lo estaba estableciendo en un valor falso, eso se devolvió implícitamente y eso hizo que el guardado fallara silenciosamente. En el lado positivo, ahora tengo la opción de corregir este código agregando la línea "Hey! That's MY fake leg!" # Believe it or not, this is important. No es que yo haría eso. ;)
Nathan Long
2
Una buena manera de garantizar un verdadero valor de retorno estrue.tap { do_something }
Nathan Long
Guau, qué tema tan oscuro. Nunca hubiera adivinado que una devolución de llamada que devolviera falso habría dejado de guardar. ¿Alguien podría indicarme los documentos sobre esto? ¡Gracias por señalar esto!
Andy
116

Intente usar la versión bang save!(con un signo de exclamación al final) e inspeccione el error resultante.

Andy Lindeman
fuente
4
¡salvar! solo está lanzando un RecordNotSaved (cuando imprimo el .message de la excepción, obtengo el nombre de la clase de excepción). ¿Hay algún lugar en el que debería buscar más detalles?
kdt
1
Si está en el modo de desarrollo de Rails, debería imprimir una descripción completa del error con seguimiento de pila. Echa un vistazo allí para encontrar pistas y / o publícalo aquí.
Andy Lindeman
1
Uso la consola, cargo el objeto (por ejemplo, o = Object.find #id), luego hago o.save! como dice la respuesta. Imprime por qué no se está guardando.
pduey
1
Para su información, la llamada save!puede aumentar ActiveRecord::RecordInvalid(ya que ejecuta validaciones) o ActiveRecord::RecordNotSavedeso es lo que querrá rescatar.
Dennis
2
+1 porque esta es la respuesta menos insatisfactoria a la pregunta fundamental de cómo diagnosticar .savefallas que no se deben a la validación. La calificación "menos insatisfactoria" se refiere a Rails, no a esta respuesta.
Chuck Batson
112

Si @user.save(por ejemplo) regresa false, simplemente ejecute esto para obtener todos los errores:

@user.errors.full_messages
Sam Alex
fuente
13
Como mencioné en la pregunta, ¿.valido? es verdadero, es decir, no hay errores de validación. He comprobado que .errors también está devolviendo una lista vacía (he actualizado la pregunta para señalarlo)
kdt
3

Sí, solucioné este problema asegurándome de devolver verdadero en todas mis devoluciones de llamada before_ * y luego comienza a funcionar :)

Lápiz
fuente
-1

El problema que tuve fue que me olvidé de agregar la validación al modelo.

class ContactGroup < ActiveRecord::Base
  validates_presence_of :name
end
Ian Vaughan
fuente